2013-08-31 9 views
5

In meinem MVVM habe ich ein DataGrid, in dem ich die Zeilenelemente basierend auf 2 Kriterien aktivieren möchte. DataGrid hat Kontrollkästchen in 1 Spalte (die an IsRowChecked Eigenschaft gebunden ist) und ein Header-Kontrollkästchen in einer anderen Spalte. Ich möchte das Zeilenelement aktivieren, wenn 1) IsRowChecked ist wahr UND 2) Header-Kontrollkästchen ausgewählt ist.WPF-Bindung für mehrere Kriterien

Ist diese Mehrfachkriterieneinstellung möglich?

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> 

"Anzahl der Chemikalien" col braucht nur einzelne Kriterien verbindlich, die ich tun konnte. Wert1 & Wert2 benötigt 2 Kriterien, z. B. IsRowChecked und Header-Kontrollkästchen ausgewählt. Ich könnte mit Single machen, bekomme aber keine Möglichkeit, 2 Kriterien in diesen Bindungen zu implementieren.

Wie kann ich diese Art der Bindung erreichen ???

Jede Hilfe wird sehr geschätzt.

Dank

Antwort

7

Im moment gibt es zwei Möglichkeiten, um mit komplexen Ausdrücken auf Bindungen zu arbeiten: MultiBinding mit einem Konverter und MultiDataTrigger mit spezifischen Fällen. Für Ihr Beispiel funktionieren beide gut.

1. Multibinding

Diese Methode ist für praktisch jeden Fall funktioniert, erfordert aber Konvertern Umsetzung (sie wiederverwendet werden können, natürlich).

  1. erstellen AndConverter Klasse Umsetzung IMultiValueConverter Schnittstelle. Es muss true zurückgegeben werden, wenn alle Werte, die an es übergeben werden, wahr sind (DependencyProperty.UnsetValue ist ein spezieller Wert, wenn Wert nicht verfügbar ist).

    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. den Konverter an Ressourcen hinzufügen:

    <Window.Resources> 
        <local:AndConverter x:Key="convAnd"/> 
    </Window.Resources> 
    
  3. DataTemplate für Value1 Spalte angeben (wird Original-Code kommentiert):

    <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. Multidatatrigger

Diese Methode funktioniert, wenn nur eine Eigenschaftswertkonfiguration ein bestimmtes Verhalten erfordert. In Ihrem Beispiel ist das Textfeld immer deaktiviert, außer wenn beide Kontrollkästchen aktiviert sind. Die Syntax ist komplexer, aber Konverter sind nicht erforderlich.

  1. Geben DataTemplate für Value2 Spalte (Original-Code wird kommentiert):

    <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> 
    
+0

Wow Athari, beide Optionen arbeiten völlig in Ordnung. Ich frage mich, welchen ich benutzen soll. In diesem Fall denke ich, dass ich nur mit MultiBinding gehen werde. Eine weitere Frage, kann ich das gleiche auf meine Header-Checkboxen implementieren - Wenn Value1-Header-Chkbox ausgewählt ist, dann darf der Benutzer nur das Value2-Header-Kontrollkästchen auswählen. Anfangs ist Value2-Header-chkbox deaktiviert, und wenn Benutzer Value1 chkValue1 auswählt, dann aktivieren Sie nur chkValue2. Kann dies in Header-Checkboxen implementiert werden ??? – Tvd

+0

@Tvd Ich habe die genauen booleschen Ausdrücke nicht verstanden, aber in jedem Fall können Sie eine 'MultiBinding' mit einem Konverter verwenden. Eine 'MultiBinding' kann beliebig viele' Binding's enthalten, deren Werte in einem 'values' Argument an die' IMultiValueConverter.Convert' Methode übergeben werden. Innerhalb dieser Methode können Sie jeden gewünschten logischen Ausdruck schreiben. Der Code, den ich in 'Convert' verwendet habe, ist ein bisschen komplex, weil er generisch ist und alle Möglichkeiten überprüft, aber im Grunde sind es' return (bool) Werte [0] && (bool) Werte [1] '. – Athari

Verwandte Themen