mauiattachedbehaviors

.Net Maui adding a Behavior to a Style


In my app I have many Entry controls on multiple pages. I also have a behavior 'EntryHighlightBehavior' that simply highlights the control and the label that identifies it. This works as expected. I also have a StaticResource that gives them consistent formatting. I would like to identify the behavior inside the element of my style so that I don't have to enumerate it each time I create a new Entry. I looked at this post Style target behaviors MAUI but it creates a command which I'm not looking to do. So any Help would be appreciated. Relevant code below: EntryHighlightBehavior

    public class EntryHighlightBehavior : Behavior<Entry>
{
    protected override void OnAttachedTo(Entry entry)
    {
        entry.Focused += OnEntryFocusChanged;
        entry.Unfocused += OnEntryFocusChanged;
        base.OnAttachedTo(entry);
    }

    protected override void OnDetachingFrom(Entry entry)
    {
        entry.Focused -= OnEntryFocusChanged;
        entry.Unfocused -= OnEntryFocusChanged;
        base.OnDetachingFrom(entry);
    }

    void OnEntryFocusChanged(object sender, FocusEventArgs e)
    {
        var myentry = sender as Entry;
        var myGrid = myentry.Parent as Grid;
        if (e.IsFocused)
            myGrid.BackgroundColor = App.HighlightColor;
        else
            myGrid.BackgroundColor = Colors.White;
    }

}

Xaml:

                    <Grid x:Name="grdCustomOptions" ColumnDefinitions="235,*" RowDefinitions="40,40" Grid.Row="2" Grid.ColumnSpan="2" IsVisible="false">
                    <Label x:Name="lblCustomoption" Text="Custom Option" Style="{StaticResource LabelEntry}" Grid.ColumnSpan="2" />
                    <Entry x:Name="entCustomoption" Placeholder="Custom Option" Style="{StaticResource EntryPlain}"
                               ReturnType="Next" Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="2" WidthRequest="400" >
                        <Entry.Behaviors>
                            <behave:EntryHighlightBehavior/>
                        </Entry.Behaviors>
                    </Entry>                        
                </Grid>

StaticResource (Style.xaml):

    <Style x:Key="EntryPlain" TargetType="Entry">
    <Setter Property="HeightRequest" Value="40"/>
    <Setter Property="Keyboard" Value="Plain"/>
    <Setter Property="ReturnType" Value="Done"/>
    <Setter Property="HorizontalOptions" Value="Start"/>
    <Setter Property="VerticalOptions" Value="Center"/>
    <Setter Property="BackgroundColor" Value="Transparent"/>
    <Setter Property="WidthRequest" Value="200"/>
    <Setter Property="Grid.Column" Value="1"/>
    <Setter Property="Grid.Row" Value="0"/>
    <Setter Property="local:KeyboardStyle.KeyboardFlags"
                    Value="Suggestions,CapitalizeCharacter"/>
    <Setter Property="behave:EntryHighlightBehavior">  <<===== How do I do this?????

    </Setter>
</Style>

Solution

  • You may refer to this Consume a .NET MAUI behavior with a style, which points out the right way to put a Behavior property into a Style.

    For your case, you may take up the following steps,

    1.Adding an attached property in your EntryHighlightBehavior. Creating a static getter and setter for it and implementing logic in the propertyChanged delegate.

    public class EntryHighlightBehavior : Behavior<Entry>
    {
         public static readonly BindableProperty AttachBehaviorProperty =
    BindableProperty.CreateAttached("AttachBehavior", typeof(bool), typeof(EntryHighlightBehavior), false, propertyChanged: OnAttachBehaviorChanged);
    
        public static bool GetAttachBehavior(BindableObject view)
        {
            return (bool)view.GetValue(AttachBehaviorProperty);
        }
    
        public static void SetAttachBehavior(BindableObject view, bool value)
        {
            view.SetValue(AttachBehaviorProperty, value);
        }
    
        static void OnAttachBehaviorChanged(BindableObject view, object oldValue, object newValue)
        {
            Entry entry = view as Entry;
            if (entry == null)
            {
                return;
            }
    
            bool attachBehavior = (bool)newValue;
            if (attachBehavior)
            {
                entry.Behaviors.Add(new EntryHighlightBehavior());
            }
            else
            {
                Behavior toRemove = entry.Behaviors.FirstOrDefault(b => b is EntryHighlightBehavior);
                if (toRemove != null)
                {
                    entry.Behaviors.Remove(toRemove);
                }
            }
        }
    
        // the following code is the same as yours
        protected override void OnAttachedTo(Entry entry)
        {
          ...
        }
    
        protected override void OnDetachingFrom(Entry entry)
        {
        ...
        }
    
        void OnEntryFocusChanged(object sender, FocusEventArgs e)
        {
             ...
        }
    }
    

    2.Consuming the Behavior it in Style,

    <Style x:Key="EntryPlain" TargetType="Entry">
        ...
        <Style.Setters>
            <Setter Property="local:EntryHighlightBehavior.AttachBehavior" Value="true" />
        </Style.Setters>
    
    </Style>
    

    Then you don't have to enumerate the Behavior property each time you create a new Entry.

    If you still have any questions, feel to ask me.

    Hope it helps!