【问题标题】:WPF Binding on multiple criteriasWPF 绑定多个条件
【发布时间】:2013-09-04 01:11:01
【问题描述】:

在我的 MVVM 中,我有一个 DataGrid,我想在其中启用基于 2 个条件的行元素。 DataGrid 在 1 col 中有复选框(绑定到 IsRowChecked 属性),在另一个 col 中有一个标题复选框。如果我想启用行元素 1) IsRowChecked 为真并且 2) 标题复选框被选中。

这种多条件设置是否可行?

XAML

<DataGrid ItemsSource="{Binding SiList, Mode=TwoWay}" Name="dgvSiSelection">
      <DataGrid.Columns>                  
          <DataGridCheckBoxColumn Binding="{Binding IsRowChecked, Mode=TwoWay}"/>  
          <DataGridTextColumn Header="" Binding="{Binding Header}" MinWidth="108" IsReadOnly="True"/>
          <DataGridTemplateColumn>
              <DataGridTemplateColumn.Header>
                    <Grid>
                        <Grid.ColumnDefinitions>
                              <ColumnDefinition />
                        </Grid.ColumnDefinitions>
                        <TextBlock Text="Number of Chemicals" Grid.Column="0"  />
                    </Grid>                                        
               </DataGridTemplateColumn.Header>
               <DataGridTemplateColumn.CellTemplate>
                     <DataTemplate>
                          <TextBlock Text="{Binding Path=NumberOfCases}" />
                     </DataTemplate>
                     </DataGridTemplateColumn.CellTemplate>
                     <DataGridTemplateColumn.CellEditingTemplate>
                          <DataTemplate>
                              <TextBox IsEnabled="{Binding Path=IsRowChecked}" Text="{Binding Path=NumberOfCases, Mode=TwoWay}" />
                         </DataTemplate>
                     </DataGridTemplateColumn.CellEditingTemplate>
                 </DataGridTemplateColumn>


                 <!-- Value1  chkValue11-->
                 <DataGridTemplateColumn>
                     <DataGridTemplateColumn.Header>
                          <Grid>
                              <Grid.ColumnDefinitions>
                                    <ColumnDefinition/>
                                    <ColumnDefinition/>
                              </Grid.ColumnDefinitions>
                              <TextBlock Grid.Column="1" Text="Value1" IsEnabled="{Binding ElementName=chkValue11, Path=IsChecked}" />
                              <CheckBox Name="chkValue11"  Grid.Column="0" Width="16" />
                          </Grid>
                     </DataGridTemplateColumn.Header>
                     <DataGridTemplateColumn.CellTemplate>
                          <DataTemplate>
                                <TextBlock Text="{Binding Path=Value1}" />
                          </DataTemplate>
                     </DataGridTemplateColumn.CellTemplate>
                     <DataGridTemplateColumn.CellEditingTemplate>
                            <DataTemplate>
                                 <TextBox IsEnabled="{Binding ElementName=chkValue11, Path=IsChecked}" Text="{Binding Path=Value1, Mode=TwoWay}" />
                            </DataTemplate>
                      </DataGridTemplateColumn.CellEditingTemplate>
                  </DataGridTemplateColumn>

                  <!-- Value2  chkValue12-->
                  <DataGridTemplateColumn>
                      <DataGridTemplateColumn.Header>
                          <Grid>
                              <Grid.ColumnDefinitions>
                                   <ColumnDefinition/>
                                   <ColumnDefinition/>
                              </Grid.ColumnDefinitions>
                              <TextBlock Grid.Column="1" Text="Value2" IsEnabled="{Binding ElementName=chkValue12, Path=IsChecked}" />
                              <CheckBox Name="chkValue12"  Grid.Column="0" Width="16" />
                          </Grid>
                    </DataGridTemplateColumn.Header>
                    <DataGridTemplateColumn.CellTemplate>
                         <DataTemplate>
                                <TextBlock Text="{Binding Path=Value2}" />
                         </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                    <DataGridTemplateColumn.CellEditingTemplate>
                          <DataTemplate>
                               <TextBox IsEnabled="{Binding ElementName=chkValue12, Path=IsChecked}" Text="{Binding Path=Value2, Mode=TwoWay}" />
                          </DataTemplate>
                    </DataGridTemplateColumn.CellEditingTemplate>
                </DataGridTemplateColumn>

       </DataGrid.Columns>
   </DataGrid>

“化学品数量”列只需要我可以做的单一标准绑定。 Value1 & Value2 需要 2 个标准,即 IsRowChecked 和选中的标题复选框。我可以使用单个,但无法在这些绑定中实现 2 个标准。

我怎样才能实现这种绑定???

非常感谢任何帮助。

谢谢

【问题讨论】:

    标签: c# .net wpf mvvm binding


    【解决方案1】:

    有两种方法可以处理绑定上的复杂表达式:MultiBinding 使用转换器,MultiDataTrigger 使用特定情况。对于您的示例,两者都运行良好。

    1.多重绑定

    这种方法几乎适用于任何情况,但需要实现转换器(它们显然可以重复使用)。

    1. 创建实现IMultiValueConverter 接口的AndConverter 类。如果传递给它的所有值都为真,则它需要返回trueDependencyProperty.UnsetValue 是一个特殊值,当值不可用时)。

      public class AndConverter : IMultiValueConverter
      {
          public object Convert (object[] values, Type targetType, object parameter, CultureInfo culture)
          {
              if (values.Any(v => ReferenceEquals(v, DependencyProperty.UnsetValue)))
                  return DependencyProperty.UnsetValue;
              return values.All(System.Convert.ToBoolean);
          }
      
          public object[] ConvertBack (object value, Type[] targetTypes, object parameter, CultureInfo culture)
          {
              throw new NotSupportedException();
          }
      }
      
    2. 将转换器添加到资源中:

      <Window.Resources>
          <local:AndConverter x:Key="convAnd"/>
      </Window.Resources>
      
    3. Value1列指定DataTemplate(原代码已注释):

      <DataTemplate DataType="local:Item">
          <!--<TextBox IsEnabled="{Binding ElementName=chkValue11, Path=IsChecked}" Text="{Binding Path=Value1, Mode=TwoWay}"/>-->
          <TextBox Text="{Binding Path=Value1, Mode=TwoWay}">
              <TextBox.IsEnabled>
                  <MultiBinding Converter="{StaticResource convAnd}">
                      <Binding ElementName="chkValue11" Path="IsChecked"/>
                      <Binding Path="IsRowChecked"/>
                  </MultiBinding>
              </TextBox.IsEnabled>
          </TextBox>
      </DataTemplate>
      

    2。多数据触发器

    当只有一个属性值配置需要特定行为时,此方法有效。在您的示例中,文本框始终处于禁用状态,除非选中 both 复选框。语法更复杂,但不需要转换器。

    1. Value2列指定DataTemplate(原代码已注释):

      <DataTemplate DataType="local:Item">
          <!--<TextBox IsEnabled="{Binding ElementName=chkValue12, Path=IsChecked}" Text="{Binding Path=Value2, Mode=TwoWay}"/>-->
          <TextBox x:Name="txt" Text="{Binding Path=Value2, Mode=TwoWay}"
                   IsEnabled="False"/>
          <DataTemplate.Triggers>
              <MultiDataTrigger>
                  <MultiDataTrigger.Conditions>
                      <Condition Binding="{Binding IsChecked, ElementName=chkValue12}" Value="True"/>
                      <Condition Binding="{Binding IsRowChecked}" Value="True"/>
                  </MultiDataTrigger.Conditions>
                  <Setter TargetName="txt" Property="IsEnabled" Value="True"/>
              </MultiDataTrigger>
          </DataTemplate.Triggers>
      </DataTemplate>
      

    【讨论】:

    • 哇,Athari,这两个选项都运行良好。我想知道使用哪一个。在这种情况下,我想我只会使用 MultiBinding。还有一个问题,我可以在我的 Header Checkboxes 上实现相同的功能吗?如果选择了 Value1 header chkbox,那么只让用户选择 Value2 header 复选框。最初 Value2 header chkbox 被禁用,当用户选择 Value1 chkValue1 时,只启用 chkValue2。这可以在标题复选框中实现吗???
    • @Tvd 我不明白确切的布尔表达式,但无论如何,您可以将MultiBinding 与转换器一起使用。一个MultiBinding 可以包含任意数量的Bindings,这些值在values 参数中传递给IMultiValueConverter.Convert 方法。在此方法中,您可以编写任何您想要的逻辑表达式。我在Convert 中使用的代码有点复杂,因为它是通用的并检查所有可能性,但基本上它是return (bool)values[0] &amp;&amp; (bool)values[1]
    猜你喜欢
    • 2017-07-05
    • 2011-01-06
    • 2019-01-31
    • 2014-05-17
    • 2011-07-06
    • 1970-01-01
    • 2011-02-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多