【问题标题】:Custom View with Bindable Property not binding properly on Xamarin.Forms SAP具有可绑定属性的自定义视图未在 Xamarin.Forms SAP 上正确绑定
【发布时间】:2023-04-08 17:03:01
【问题描述】:

我有一个复选框应该触发按钮的 IsEnabled 事件。但是不知何故,应该执行的命令永远不会正确绑定并因此执行。

这是 CheckBox.xaml.cs(控件)中的可绑定属性:

public static readonly BindableProperty CheckBoxCommandProperty =
       BindableProperty.Create<CheckBox, ICommand>(
       checkbox =>
           checkbox.CheckBoxCommand,
           null,
           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); }
   }

这就是我在 ViewModel 上的内容:

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

   public TermsAndConditionsViewModel()
   {
       Next_OnClick = new Command(NextClicked);
       OnCheckBoxTapChanged = new Command(CheckBoxTapped);
   }

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

CheckBoxTapped 方法永远不会被执行,因此我要设置的按钮属性永远不会改变。

提前谢谢各位!

【问题讨论】:

  • 为什么不能同时绑定按钮可见性到某个 bool 属性,然后绑定到使用转换器检查的相同属性绑定复选框?

标签: c# mvvm xamarin xamarin.forms shared-project


【解决方案1】:

你可以把这个问题的解决方法分成几个层次:

首先,为复选框创建一个可绑定属性,并将其命名为 Checked。 我已经为它写了一个片段,但并没有真正编译它,所以如果它不起作用,你可能想修改它

  public static readonly BindableProperty IsCheckedProperty = 
    BindableProperty.Create<CheckBox, bool> (w => w.IsChecked, false);

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

其次,在视图模型中创建一个具有更改通知的 bool 属性

private bool _isChecked;
public bool IsChecked
{
    get 
    { 
        return _isChecked;
    }
    set
    {
        _isChecked = value;
        RaisePropertyChanged("IsChecked");
    }
} 

第三,将复选框“isChecked”的可绑定属性绑定到 xaml 中视图模型中的属性:

<StackLayout>
    <Checkbox IsChecked = "{Binding IsChecked}"/>
</StackLayout>

第四,带有 MVVM 的 Xaml 中的按钮绑定到命令。在这些命令中,它们有一个 bool 属性,代表“CanExecute”,它基本上启用或禁用按钮。所以你在 Xaml 中要做的就是将按钮的命令绑定到视图模型中的命令(我们称之为 ClickCommand)。而ClickCommand的CanExecute其实只是一个返回“IsChecked”值的方法。 这将使我们修改“IsChecked”属性的设置器,因此每次更改时都应通知命令检查 CanExecute 属性。

所以最终的代码会是这样的

public TermsAndConditionsViewModel()
   {
       NextCommand = new Command(ExecuteNextCommand,CanExecuteNextCommand);
       OnCheckBoxTapChanged = new Command(CheckBoxTapped);
   }


private bool _isChecked;
public bool IsChecked
{
    get { return _isChecked;}
    set
    {
         _isChecked = value;
    NextCommand.ChangeCanExecute(); //this will actually notify the command to enable/disable
        RaisePropertyChanged("IsChecked");
    }
}


public Command NextCommand {get;set;} // this type is available in Xamarin.Forms library
private bool CanExecuteNextCommand()
{
    return IsChecked;
}
private void ExecuteNextCommand()
{
    // your execution when the button is pressed    
}

Xaml 就像

<StackLayout>
    <Checkbox IsChecked = "{Binding IsChecked}"/>
    <Button Text= "Next" Command = "{Binding NextCommand}"/>
</StackLayout> 

【讨论】:

    【解决方案2】:

    使用 Xamarin.Forms.Behavior 解决了这个问题。它允许多个控件绑定。

    例如>

    <Entry Placeholder="Enter password"
                 Text= "{Binding TxtFirstPasswordInput}"
                 IsPassword="true">
            <b:Interaction.Behaviors>
              <b:BehaviorCollection>
                <b:EventToCommand EventName="Unfocused" Command="{Binding entry_Finished}"/>
                <b:EventToCommand EventName="Focused" Command="{Binding entry_Focused}"/>
              </b:BehaviorCollection>
            </b:Interaction.Behaviors>
          </Entry>
    

    在 ViewModel 上>

    public PasswordInputViewModel()
            {
                entry_Finished = new Command(validateAndContinue);//unfocused
                entry_Focused = new Command(entryFocused); //focused
            }
    

    【讨论】:

      猜你喜欢
      • 2015-12-12
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-06-16
      • 2016-12-23
      相关资源
      最近更新 更多