【问题标题】:Xamarin Custom Control Binding Not WorkingXamarin 自定义控件绑定不起作用
【发布时间】:2020-08-13 22:50:23
【问题描述】:

我创建了一个名为 Switch 的 ContentView,主要将此滑块作为自定义控件托管,以便我可以重用打开和关闭的视觉状态。

ContentView 包含一个标签(仅用于调试)和一个 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

我无法弄清楚为什么标签和命令都没有做任何事情。在调试期间,LabelText 不显示

当我滑动开关时,EventToCommandBehavior 中的这个断点显示没有命令与事件相关联。 null 命令防止调用视图模型中的处理程序。

【问题讨论】:

  • 是否需要将Switch的BindingContext设置为自身?
  • 在你的构造函数中,你需要将你的自定义控件的BindingContext设置为自身,this.BindingContext= this;
  • 奇怪的是,添加 BindingContext = this,修复了缺少的 LabelText 但命令仍然为空。
  • 我还尝试通过挂钩到 SfSwitch 的 StateChanged 事件来调用代码隐藏中的命令。即使在那里,StateChangedCommand 也是空的。
  • 这里的命令是什么?状态改变命令?能否请您显示一些更相关的线程。

标签: xamarin commandbinding


【解决方案1】:

对此感到困惑,翻阅了 EventToCommandBehavoir 源代码和几十个 StackOverflow 帖子后,我终于找到了问题。

我发现有两件事需要注意:

首先是 EventToCommandBehavoir 只需要 Xamarin.Forms.Command,而不仅仅是任何 ICommand。

第二个,非常感谢this 的帖子,ContentView 必须在其构造函数中包含这个命令才能工作(但不适用于文本等其他类型)。

Content.BindingContext = this;

因为有多个 ICommand 实现(特别是在您需要 AsyncCommand 时很有用),而且 Labels 和这样的实现在不设置 Content.BindingContext 的情况下也能正常工作,因此很容易被 EventToCommandBehavior 混淆。

【讨论】:

    猜你喜欢
    • 2021-02-18
    • 1970-01-01
    • 2015-04-25
    • 1970-01-01
    • 2021-07-04
    • 2019-12-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多