【问题标题】:WPF databinding IsEnabled PropertyWPF 数据绑定 IsEnabled 属性
【发布时间】:2009-02-11 13:44:18
【问题描述】:

所以我现在正在学习 WPF,并且想在 bool 值和 MenuItem 是否启用之间进行简单的数据绑定。

我是这样编码的:

<MenuItem Name="miSaveFile" Header="Save" Click="miSaveFile_Click"
IsEnabled="{Binding}" />

在我设置的 .cs 文件中:

miSaveFile.DataContext = dataChanged;

由于某种原因,MenuItem 似乎没有正确反映 dataChanged 的​​状态。

我错过了什么?

【问题讨论】:

    标签: wpf data-binding menuitem isenabled


    【解决方案1】:

    你最好绑定到一个对象而不是一个原始类型。该对象通常被称为您的视图的“模型”。

    WPF 使用模型(或通常是视图模型)的 INotifyPropertyChanged 接口来通知视图模型已更改状态。

    因此,您首先需要将数据类定义为实现 INotifyPropertyChanged 接口并在属性更改时触发 PropertyChanged 事件的模型。

    当您设置绑定时,您需要担心绑定上的 5 个主要元素。绑定具有源对象、源对象上的源路径、目标对象、目标对象上的目标属性和可选的转换器。

    如果不指定源,则默认为设置绑定的控件的 DataContext。还有其他用于设置源的选项。 Here 是一篇关于设置源的 Microsoft 文章。然后,您可以设置属性的路径以从绑定源中拉出。在您的情况下,源是一个布尔值并且没有路径,因为绑定正在使用整个源对象。

    目标始终是您设置绑定的控件,目标属性是您要绑定到的该控件的属性。在这种情况下,MenuItem 和 IsEnabled。

    转换器可以选择将源值转换为与目标属性兼容的值。您可以将任何对象用于实现 IValueConverter 或 IMultiValueConverter(用于 MutliBindings)的转换器。

    在您的情况下,我将首先创建一个实现 INotifyPropertyChanged 的​​模型。接下来,我会将菜单的 DataContext 分配给模型的一个实例。然后我将绑定设置为:

    IsEnabled="{Binding Path=EnableFlag}"
    

    (其中 EnableFlag 是模型中您希望通过菜单绑定到的布尔属性)

    如果您正确设置了 INotifyPropertyChanged 接口,则每当您在模型上更改此属性时,菜单项将被启用/禁用。

    【讨论】:

      【解决方案2】:

      对于 MenuItem,使用 Command 模型而不是 Click 和 IsEnabled 属性不是更好的方法吗?

      InitialiseComponent() 之后:

      this.CommandBindings.Add(new CommandBinding(ApplicationCommands.Save, fileSaveExecuted, fileSaveCanExecute));
      

      其他方法:

      /* here is where you set e.CanExecute true for enabled: */
          private void fileSaveCanExecute(object x, CanExecuteRoutedCommandEventArgs e)) { e.CanExecute = ...; e.Handled = true; }
      /* here is where you act on the command: */
          private void fileSaveExecuted(object sender, ExecutedRoutedEventArgs e) { ... }
      

      XAML:

      <MenuItem Header="_Save" Command="Save"/>
      

      【讨论】:

        【解决方案3】:

        UI 如何知道 dataChanged 变量何时实际发生了变化?

        我通常绑定到对象的属性,并让该类实现 INotifyPropertyChanged。每当调用 PropertyChanged 事件时,UI 就会“自动”更新。

        所以我会的

        <MenuItem Name="miSaveFile" Header="Save" Click="miSaveFile_Click"
        IsEnabled="{Binding DataChanged}"</MenuItem>
        

        然后设置 miSaveFile.DataContext = myObject.DataChanged (如果您使用的是代码隐藏,myObject 可以是这个)

        编辑:我刚刚做了一个快速测试。如果将数据上下文直接设置为 DataChanged 属性,则不会添加对所有者对象的 PropertyChanged 事件的订阅。但我建议的解决方案有效。

        【讨论】:

        • "UI 如何知道 dataChanged 变量何时实际发生了变化?"好问题。现在我还处于 Data_Binding-Is-Voodoo 阶段:)
        • 如果您想真正了解正在发生的事情(巫毒教的东西),您可以在 Visual Studio 中启用 .Net 框架单步执行并查看实际执行的代码 :)