在Xamarin Forms上创建ICommand Bindable属性 [英] Create an ICommand Bindable property on Xamarin Forms

查看:134
本文介绍了在Xamarin Forms上创建ICommand Bindable属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个自定义复选框控件,该控件是使用ICommand属性和相应的可绑定属性(我的复选框是Xamarin.Forms XAML页面)创建的,代码是:

I have a custom checkbox control that I created with an ICommand property and the corresponding bindable property (my checkbox is a Xamarin.Forms XAML Page), the code is:

CheckBox.xaml

<Image x:Name="imgCheckBox"
       WidthRequest="20"
       HeightRequest="20"/>

<Label x:Name="lblCheckBox"
       TextColor="Black"
       VerticalOptions="CenterAndExpand"/>

<TapGestureRecognizer Tapped="OnCheckBoxTapped"/>

CheckBox.xaml.cs

public partial class CheckBox : ContentView
{
    private static ImageSource uncheckedImage;
    private static ImageSource checkedImage;

    public CheckBox()
    {
        InitializeComponent();
        uncheckedImage = ImageSource.FromResource("cbUnchecked.png");
        checkedImage = ImageSource.FromResource("cbChecked.png");
        imgCheckBox.Source = uncheckedImage;
    }

    public static readonly BindableProperty IsCheckedProperty =
        BindableProperty.Create<CheckBox, bool>(
            checkbox => 
                checkbox.IsChecked,
                false,
                propertyChanged: (bindable, oldValue, newValue) =>
                {
                    CheckBox checkbox = (CheckBox)bindable;
                    EventHandler<bool> eventHandler = checkbox.CheckedChanged;
                    if (eventHandler != null)
                    {
                        eventHandler(checkbox, newValue);
                    }
                });        

    public bool IsChecked
    {
        set { SetValue(IsCheckedProperty, value); }
        get { return (bool)GetValue(IsCheckedProperty); }
    }

    void OnCheckBoxTapped(object sender, EventArgs args)
    {
        IsChecked = !IsChecked;
        if (IsChecked)
        {
            imgCheckBox.Source = checkedImage;
        }
        else
        {
            imgCheckBox.Source = uncheckedImage;
        }
    }

    public static readonly BindableProperty CheckBoxCommandProperty =
        BindableProperty.Create<CheckBox, ICommand>(
        checkbox =>
            checkbox.CheckBoxCommand,
            null,
            BindingMode.TwoWay,
            propertyChanged: (bindable, oldValue, newValue) =>
            {
                CheckBox checkbox = (CheckBox)bindable;
                EventHandler<bool> eventHandler = checkbox.CheckedChanged;
                if (eventHandler != null)
                {
                    eventHandler(checkbox, checkbox.IsChecked);
                }
            });

    public event EventHandler<bool> CheckedChanged;

    public ICommand CheckBoxCommand
    {
        get { return (ICommand)GetValue(CheckBoxCommandProperty); }
        set { SetValue(CheckBoxCommandProperty, value); }
    }
}

此复选框实现位于另一个名为TermsAndConditionsPage的页面上,该页面也是Xamarin.Forms XAML页面,实现的代码为:

This checkbox implementation is on another Page called TermsAndConditionsPage, that is also a a Xamarin.Forms XAML Page, the code of the implementation is:

<toolkit:CheckBox Text="{Binding txtCheckBox}"
                  FontSize="Small"
                  CheckBoxCommand="{Binding OnCheckBoxTapChanged}"
                  IsChecked="{Binding IsCheckedChanged, Mode=TwoWay}"/>

      <Button Text="Next"
              Command="{Binding Next_OnClick}"
              IsEnabled="{Binding Next_IsEnabled}"
              HorizontalOptions="CenterAndExpand"
              Clicked="OnNextClicked"/>

此页面后面的代码为空(使用InitializeComponent()构造). 我也有此页面的ViewModel,其中包含以下代码:

The Code Behind of this page is empty (Constructur with InitializeComponent()). I also have the ViewModel of this page with this code:

TermsAndConditionsViewModel.cs

private string _txtCheckBox;
public string txtCheckBox
{ get { return _txtCheckBox; }
    set 
    { 
        _txtCheckBox = value;
        OnPropertyChanged("txtCheckBox");
    }
}

private bool _Next_IsEnabled;
public bool Next_IsEnabled
{
    get { return _Next_IsEnabled; }
    set
    {
        _Next_IsEnabled = value;
        OnPropertyChanged("Next_IsEnabled");
    }
}

private bool _IsCheckedChanged;
public bool IsCheckedChanged
{
    get { return _IsCheckedChanged; }
    set 
    { 
        _IsCheckedChanged = value;
        OnPropertyChanged("IsCheckedChanged");
    }
}

public ICommand Next_OnClick { get; set; }
public ICommand OnCheckBoxTapChanged { get; set; }

public TermsAndConditionsViewModel()
{
    txtCheckBox = "I agree with the terms and conditions";
    Next_OnClick = new Command(NextClicked);
    OnCheckBoxTapChanged = new Command(CheckBoxTapped);
}

private void CheckBoxTapped()
{
    if (IsCheckedChanged)
    { Next_IsEnabled = true; }
    else
    { Next_IsEnabled = false; }
}

private void NextClicked()
{ App.Current.MainPage = new Views.HelloWorld(); }

#region INPC
public void OnPropertyChanged(string propertyName)
{
    if (PropertyChanged != null)
    { PropertyChanged(this, new PropertyChangedEventArgs(propertyName));          }                
}
public event PropertyChangedEventHandler PropertyChanged;
#endregion  

现在,提问时间:我遇到的问题是CheckBoxTapped Command不起作用,我的意思是,它什么也没有做,尽管每次我触摸复选框图像都会更改,但它不会更改Next_IsEnabled我的按钮的属性.我想知道我在这里缺少什么来使此命令正常工作.

Now, the question time: the problem I'm having is the CheckBoxTapped Command is not working, I mean, it doesn't do anything, although the checkbox image changes every time I touch it, it does not change the Next_IsEnabled property of my button. I'd like to know what I am missing here to make this command work properly.

编辑

我要寻找的是一个与Button具有相似行为的命令.

What I'm looking for is a Command that behaves similarly to the one that Buttons have.

感谢您的光临!

推荐答案

由于原始答案现在已过时,因此这是新方法:

Since the original answer is now obsolete, here is the new method:

using System.Windows.Input;

public partial class MyControlExample : ContentView
{
    // BindableProperty implementation
    public static readonly BindableProperty CommandProperty = 
        BindableProperty.Create(nameof(Command), typeof(ICommand), typeof(MyControlExample), null);

    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    // Helper method for invoking commands safely
    public static void Execute(ICommand command)
    {
        if (command == null) return;
        if (command.CanExecute(null))
        {
            command.Execute(null);
        }
    }

    public MyControlExample()
    {
        InitializeComponent();
    }

    // this is the command that gets bound by the control in the view
    // (ie. a Button, TapRecognizer, or MR.Gestures)
    public Command OnTap => new Command(() => Execute(Command));
}

这篇关于在Xamarin Forms上创建ICommand Bindable属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆