【问题标题】:set button datacontext to multiple elements将按钮数据上下文设置为多个元素
【发布时间】:2011-01-26 04:25:14
【问题描述】:

当我的窗口中出现验证错误时,我需要禁用一个按钮。可能发生这些错误的项目都是文本框。

我已经像这样绑定了我的 Button 的数据上下文:

DataContext="{Binding ElementName=txtEmail}"

现在有了这个,我可以在电子邮件文本框中发生验证错误时将按钮样式设置为禁用,但是当它出现在我窗口的其他文本框中时,我也想这样做?

如何将此绑定设置为多个文本框?

【问题讨论】:

    标签: wpf binding triggers styles


    【解决方案1】:

    你不能,至少不能直接。您可以将 MultiBinding 与所有所需的文本框一起用作输入,但您需要提供 IMultiValueConverter 以将各种文本框“组合”成一个对象(例如列表):

    <Button>
      <Button.DataContext>
        <MultiBinding Converter="{StaticResource ListMaker}">
          <Binding ElementName="txtEmail" />
          <Binding ElementName="txtFirstName" />
          <Binding ElementName="txtLastName" />
        </MultiBinding>
      </Button.DataContext>
    </Button>
    

    然后将结果列表对象传递给您的触发器,因此您将无法直接访问 Validation.HasError 属性:您的 DataTrigger 还需要引入一个转换器来转换列表对象转换成一个布尔值,指示是否为列表中的任何内容设置了 Validation.HasError。此时,您不妨忘记触发器并使用 MultiBinding 绑定 IsEnabled:

    <Button>
      <Button.IsEnabled>
        <MultiBinding Converter="{StaticResource AllFalse}">
          <Binding Path="(Validation.HasError)" ElementName="txtEmail" />
          <Binding Path="(Validation.HasError)" ElementName="txtFirstName" />
          <Binding Path="(Validation.HasError)" ElementName="txtLastName" />
        </MultiBinding>
      </Button.DataContext>
    </Button>
    

    (这里 AllFalse 转换器在所有输入为假时返回真,如果任何输入为真则返回假。)

    然而,更好的方法可能是,而不是将 Button 直接绑定到其他 UI 元素,让您的数据对象 - 与您的文本框绑定到的相同对象 - 公开 IsValid 属性(带有适当的更改通知),并将您的 Button.IsEnabled 绑定到:

    <Button IsEnabled="{Binding IsValid}" />
    

    这使您转向 MVVM 风格的解决方案,该解决方案有助于提高可测试性(例如,为 IsValid 属性创建测试很容易;为 Button.IsEnabled 创建测试要困难得多)。

    【讨论】:

    • 非常感谢您给我这些选项!我会选择你的最后一个选项,你能详细说明一下如何去做吗?
    • 确切的方法将取决于您目前如何实施验证。假设它是一种 IDataErrorInfo 方法,您知道哪些字段当前无效。然后,您只需创建一个只读 IsValid 属性,如果任何字段当前无效,则该属性返回 true。并且在您的每个属性设置器中,您将为 IsValid 属性提高 PropertyChanged,以便 WPF 在每次将绑定推送到数据对象后重新查询它。 (否则 WPF 不会知道刷新 Button.IsEnabled 绑定。)这有意义吗?
    • 有点...我正在使用 IDataErrorInfo。但是我很困惑的 propertychanged 位?谁加注,谁处理?我虽然 IsValid 应该提出和其他处理?没有?
    • 还有一点,如何检查字段是否无效?您必须以某种方式对其进行跟踪,还是应该处理什么 propertychanged?
    • "如何检查字段是否无效?"我有点假设您已经出于 IDataErrorInfo 的目的这样做了——即您已经有一个 IDataErrorInfo 的实现,它检查字段是否无效(以便为 IDataErrorInfo.Item 生成适当的错误字符串)。所以你希望可以重复使用它。
    【解决方案2】:

    对于 MVVM 方法,您可以尝试从 ICommand 实现命令路由器。

    <Button Command="{Binding Path=Commands.MyButtonCommand}" Style="{StaticResource MyButtonStyle}" ></Button>
    

    Commands 属性是 ViewModel 的一部分。然后,您可以控制该命令实现的功能以及它是否启用。这样测试就容易多了。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-03-05
      • 1970-01-01
      • 2013-08-03
      • 1970-01-01
      • 2020-10-31
      • 2019-02-15
      相关资源
      最近更新 更多