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>
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.