Xamarin 自定义控件绑定不起作用
Xamarin Custom Control Binding Not Working
我创建了一个名为 Switch 的 ContentView,主要将此滑块作为自定义控件托管,这样我就可以重复使用打开和关闭的视觉状态。
ContentView 包含一个 Label(仅用于调试)和一个 Syncfusion Switch 以及一些 VisualStateManager 内容。 Label和Switch在后面的代码中绑定到BindableProperies,Switch使用EventToCommandBehavior,所以我怀疑这是一个Syncfusion问题。
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:core="clr-namespace:FEOD.Core;assembly=FEOD"
xmlns:buttons="clr-namespace:Syncfusion.XForms.Buttons;assembly=Syncfusion.Buttons.XForms"
mc:Ignorable="d"
x:Class="FEOD.Views.Components.Switch">
<ContentView.Content>
<StackLayout>
<Label Text="{Binding LabelText}" TextColor="Black" />
<buttons:SfSwitch VisualType="Cupertino" WidthRequest="50" HeightRequest="25">
<buttons:SfSwitch.Behaviors>
<core:EventToCommandBehavior EventName="StateChanged" Command="{Binding StateChangedCommand}"/>
</buttons:SfSwitch.Behaviors>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="On">
<VisualState.Setters>
<Setter Property="SwitchSettings">
<Setter.Value>
<buttons:DefaultSwitchSettings
x:TypeArguments="buttons:OnState"
ThumbBorderColor="#039CDE" ThumbColor="#FFFFFF"
TrackBorderColor="#039CDE" TrackColor="#039CDE"/>
</Setter.Value>
</Setter>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Off">
<VisualState.Setters>
<Setter Property="SwitchSettings">
<Setter.Value>
<buttons:DefaultSwitchSettings
x:TypeArguments="buttons:OffState"
ThumbBorderColor="#E77C21" ThumbColor="#FFFFFF"
TrackBorderColor="#E77C21" TrackColor="#E77C21"/>
</Setter.Value>
</Setter>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</buttons:SfSwitch>
</StackLayout>
</ContentView.Content>
Bindable 背后的代码
using System.Windows.Input;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace FEOD.Views.Components
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Switch : ContentView
{
public static readonly BindableProperty StateChangedCommandProperty = BindableProperty.Create(
propertyName: nameof(StateChangedCommand),
returnType:typeof(ICommand),
declaringType:typeof(Switch),
defaultValue:default(ICommand),
defaultBindingMode: BindingMode.OneWay
);
public ICommand StateChangedCommand
{
get => (ICommand) GetValue(StateChangedCommandProperty);
set => SetValue(StateChangedCommandProperty, value);
}
public static readonly BindableProperty LabelTextProperty = BindableProperty.Create(nameof(LabelText), typeof(string), typeof(Switch), string.Empty, BindingMode.TwoWay);
public string LabelText
{
get => (string) GetValue(LabelTextProperty);
set => SetValue(LabelTextProperty, value);
}
public Switch()
{
InitializeComponent();
}
}
}
ContentView 托管在 ContentPage 中。它的两个属性设置如下:
<components:Switch Grid.Column="1" LabelText="MY LABel" StateChangedCommand="{Binding CreatorOrContributorFinderCommand}" />
其中 LabelText 设置为“MY LABel”,StateChangedCommand 设置为视图模型命令“CreatorOrContributorFinderCommand”。页面的 BindingContext 设置为视图模型的一个实例
public ICommand CreatorOrContributorFinderCommand { get; private set; }
private async Task OnCreatorOrContributorFinderChanged()
{
var a = 1;
}
constructor has this line:
CreatorOrContributorFinderCommand = new AsyncCommand(OnCreatorOrContributorFinderChanged);
注意:AsyncCommand 来自 https://johnthiriet.com/mvvm-going-async-with-async-command
我不明白为什么 Label 和命令都没有做任何事情。调试期间,LabelText 未显示
当我滑动开关时,EventToCommandBehavior 中的这个断点显示没有命令与事件相关联。 null 命令阻止调用视图模型中的处理程序。
在对此感到困惑并浏览 EventToCommandBehavoir 源代码和数十个 Whosebug posting 之后,我终于找到了问题所在。
我发现有两点需要注意:
首先是 EventToCommandBehavoir 只需要一个 Xamarin.Forms.Command,而不是任何 ICommand。
第二个,非常感谢 post,ContentView 必须在其构造函数中包含这个 才能使命令工作 (虽然,不是其他类型,如文本)。
Content.BindingContext = this;
因为有多个 ICommand 实现(特别是当您需要 AsyncCommand 时很有用)并且 Labels 等无需设置即可正常工作 Content.BindingContext,因此很容易被 EventToCommandBehavior 混淆。
我创建了一个名为 Switch 的 ContentView,主要将此滑块作为自定义控件托管,这样我就可以重复使用打开和关闭的视觉状态。
ContentView 包含一个 Label(仅用于调试)和一个 Syncfusion Switch 以及一些 VisualStateManager 内容。 Label和Switch在后面的代码中绑定到BindableProperies,Switch使用EventToCommandBehavior,所以我怀疑这是一个Syncfusion问题。
<?xml version="1.0" encoding="UTF-8"?>
<ContentView xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:core="clr-namespace:FEOD.Core;assembly=FEOD"
xmlns:buttons="clr-namespace:Syncfusion.XForms.Buttons;assembly=Syncfusion.Buttons.XForms"
mc:Ignorable="d"
x:Class="FEOD.Views.Components.Switch">
<ContentView.Content>
<StackLayout>
<Label Text="{Binding LabelText}" TextColor="Black" />
<buttons:SfSwitch VisualType="Cupertino" WidthRequest="50" HeightRequest="25">
<buttons:SfSwitch.Behaviors>
<core:EventToCommandBehavior EventName="StateChanged" Command="{Binding StateChangedCommand}"/>
</buttons:SfSwitch.Behaviors>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="On">
<VisualState.Setters>
<Setter Property="SwitchSettings">
<Setter.Value>
<buttons:DefaultSwitchSettings
x:TypeArguments="buttons:OnState"
ThumbBorderColor="#039CDE" ThumbColor="#FFFFFF"
TrackBorderColor="#039CDE" TrackColor="#039CDE"/>
</Setter.Value>
</Setter>
</VisualState.Setters>
</VisualState>
<VisualState x:Name="Off">
<VisualState.Setters>
<Setter Property="SwitchSettings">
<Setter.Value>
<buttons:DefaultSwitchSettings
x:TypeArguments="buttons:OffState"
ThumbBorderColor="#E77C21" ThumbColor="#FFFFFF"
TrackBorderColor="#E77C21" TrackColor="#E77C21"/>
</Setter.Value>
</Setter>
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</buttons:SfSwitch>
</StackLayout>
</ContentView.Content>
Bindable 背后的代码
using System.Windows.Input;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace FEOD.Views.Components
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class Switch : ContentView
{
public static readonly BindableProperty StateChangedCommandProperty = BindableProperty.Create(
propertyName: nameof(StateChangedCommand),
returnType:typeof(ICommand),
declaringType:typeof(Switch),
defaultValue:default(ICommand),
defaultBindingMode: BindingMode.OneWay
);
public ICommand StateChangedCommand
{
get => (ICommand) GetValue(StateChangedCommandProperty);
set => SetValue(StateChangedCommandProperty, value);
}
public static readonly BindableProperty LabelTextProperty = BindableProperty.Create(nameof(LabelText), typeof(string), typeof(Switch), string.Empty, BindingMode.TwoWay);
public string LabelText
{
get => (string) GetValue(LabelTextProperty);
set => SetValue(LabelTextProperty, value);
}
public Switch()
{
InitializeComponent();
}
}
}
ContentView 托管在 ContentPage 中。它的两个属性设置如下:
<components:Switch Grid.Column="1" LabelText="MY LABel" StateChangedCommand="{Binding CreatorOrContributorFinderCommand}" />
其中 LabelText 设置为“MY LABel”,StateChangedCommand 设置为视图模型命令“CreatorOrContributorFinderCommand”。页面的 BindingContext 设置为视图模型的一个实例
public ICommand CreatorOrContributorFinderCommand { get; private set; }
private async Task OnCreatorOrContributorFinderChanged()
{
var a = 1;
}
constructor has this line:
CreatorOrContributorFinderCommand = new AsyncCommand(OnCreatorOrContributorFinderChanged);
注意:AsyncCommand 来自 https://johnthiriet.com/mvvm-going-async-with-async-command
我不明白为什么 Label 和命令都没有做任何事情。调试期间,LabelText 未显示
当我滑动开关时,EventToCommandBehavior 中的这个断点显示没有命令与事件相关联。 null 命令阻止调用视图模型中的处理程序。
在对此感到困惑并浏览 EventToCommandBehavoir 源代码和数十个 Whosebug posting 之后,我终于找到了问题所在。
我发现有两点需要注意:
首先是 EventToCommandBehavoir 只需要一个 Xamarin.Forms.Command,而不是任何 ICommand。
第二个,非常感谢
Content.BindingContext = this;
因为有多个 ICommand 实现(特别是当您需要 AsyncCommand 时很有用)并且 Labels 等无需设置即可正常工作 Content.BindingContext,因此很容易被 EventToCommandBehavior 混淆。