mauisettereventtocommand

Style target behaviors MAUI


I want to create styled editor for my current page. I use it few times so i decide to wrote style for this element and wondering how to use Behaviors inside style. If i do this like regular way, everything is working fine

<Editor Style="{StaticResource TestEditor}"/>
<Editor.Behaviors>
<toolkit:EventToCommandBehavior 
                        EventName="Unfocused"
                        Command="{Binding Source={x:Reference TestEditorPage}, Path=BindingContext.UnfocusedCommand}"
                       CommandParameter="{Binding .}">
                        
                    </toolkit:EventToCommandBehavior>

</Editor.Behaviors>
</Editor>

So how to do the same but in my style if it is possible:

 <Style x:Key="TestEditor"
           TargetType="Editor">

        <Setter Property="AutoSize" Value="TextChanges"/>
        <Setter Property="Grid.Column" Value="1"/>
        <Setter Property="Placeholder" Value="Enter question answer"/>
        <Setter Property="Text" Value="{Binding Source={RelativeSource AncestorType={x:Type models:TestAnswerResponce}}, Path=Answer}"/>

        <Setter Property="Behaviors">

            <!-- Behavior -->
            
        </Setter>           
        
    </Style>

Solution

  • However, creating a style that sets the Behaviors property of a control is not possible because the property is read-only. The solution is to add an attached property to the behavior class that controls adding and removing the behavior.

    As a workaround, you could set the value of attach property to EventToCommandBehavior. Try the following code:

    First, create a behaviour class in which adds an attached property.

    public class MyEditorStyleBehavior : Behavior<Editor>
    {
        public static readonly BindableProperty AttachBehaviorProperty =
                BindableProperty.CreateAttached("AttachBehavior", typeof(object), typeof(MyEditorStyleBehavior), null,propertyChanged: OnAttachBehaviorChanged);
    
        public static object GetAttachBehavior(BindableObject view)
        {
            return (object)view.GetValue(AttachBehaviorProperty);
        }
    
        public static void SetAttachBehavior(BindableObject view, object value)
        {
            view.SetValue(AttachBehaviorProperty, value);
        }
    
        static void OnAttachBehaviorChanged(BindableObject view, object oldValue, object newValue)
        {
            Editor editor = view as Editor;
            if (editor == null)
            {
                return;
            }
    
            EventToCommandBehavior attachBehavior = newValue as EventToCommandBehavior;
            editor.Behaviors.Add(attachBehavior);
        }
    }
    

    And in xaml, consume the behaviour.

    This is my xaml:

    <ContentPage.Resources>
    
    <Style x:Key="TestEditor" TargetType="Editor">
    
       <Setter Property="AutoSize" Value="TextChanges"/>
    
       <Setter Property="Placeholder" Value="Enter question answer"/>
       <Setter Property="Text" Value="{Binding MyEditorText}"/>
    
        <Setter Property="local:MyEditorStyleBehavior.AttachBehavior">
            <Setter.Value>
                <toolkit:EventToCommandBehavior  EventName="Unfocused" 
                   Command="{Binding Source={x:Reference TestEditorPage}, Path=BindingContext.UnfocusedCommand}"
                   />
            </Setter.Value>
        </Setter>
    </ContentPage.Resources>
    
    <ScrollView>
        <VerticalStackLayout
            Spacing="25"
            Padding="30,0"
            VerticalOptions="Center">
    
            <Editor x:Name="myeditor" Style="{StaticResource TestEditor}"/>
    
            <Editor x:Name="myeditor1" Style="{StaticResource TestEditor}"/>
    
        </VerticalStackLayout>
    </ScrollView>
    

    In code behind .cs file, don't forget to set the bindingContext for the page.

    public MainPage()
    {
        InitializeComponent();
        this.BindingContext = new MainPageViewModel();
    }
    

    In ViewModel, I define the UnfocusedCommand and MyEditorText property. And each time editor lose focus (tap the entry below it), the command will fire.

    public string MyEditorText { get; set; }
    
    public Command UnfocusedCommand
    {
        get
        {
            return new Command(() =>
            {
                Console.WriteLine("12345");
            });
        }
    }
    
    public MainPageViewModel()
    {
        MyEditorText = "MyEditorText";
    }
    

    Hope it works.