问题描述
我创建了一个名为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源代码和数十个StackOverflow帖子之后,我终于找到了问题。
我发现有两点需要注意:
首先,EventToCommandBehavoir只需要一个 Xamarin.Forms.Command ,而不仅仅是一个ICommand。
第二个,非常感谢this的帖子,ContentView必须在其构造函数中具有此功能,命令才能正常工作(尽管不适用于文本等其他类型)。
Content.BindingContext = this;
因为有多个ICommand实现(特别是在需要AsyncCommand的情况下很有用),并且Labels等在不设置Content.BindingContext的情况下也可以正常工作,所以很容易被EventToCommandBehavior弄混。