2016-09-09 2 views
1

Ich habe ein DataGrid mit einer DataGridComboBoxColumn Spalte und ich muss eine Checkbox-Zelle in einer anderen Spalte aktivieren oder deaktivieren, aber mein Code scheint nicht zu funktionieren.Deaktivieren Sie eine Zelle in WPF-Datagrid, wenn Combo-Wert auf einen Wert gesetzt ist - MVVM

Ich habe den folgenden Code definiert, meine Combo Spalte:

<DataGridComboBoxColumn Header="Location" 
SelectedValueBinding="{Binding LocationId, Mode=TwoWay}" 
SelectedValuePath="LocationId" 
DisplayMemberPath="LocationText" 
TextBinding="{Binding Location, Mode=TwoWay}"> 

und dies ist der Code für meine Checkbox Spalte:

<DataGridCheckBoxColumn Header="Active" 
Binding="{Binding IsActive}"> 
    <DataGridCheckBoxColumn.CellStyle> 
    <Style TargetType="DataGridCell"> 
     <Style.Triggers> 
     <DataTrigger Binding="{Binding SelectedLineItem.Location}" 
      Value="01"> 
      <Setter Property="IsEnabled" Value="False" /> 
     </DataTrigger>           
     </Style.Triggers> 
    </Style> 
    </DataGridCheckBoxColumn.CellStyle> 
</DataGridCheckBoxColumn> 

ich hinzugefügt habe ein Datatrigger zu erfassen, um zu versuchen, wenn die Location-Feld ändert sich zu 01, und basierend darauf versuche ich, die Checkbox-Zelle in der ausgewählten Zeile zu deaktivieren, aber es funktioniert nicht.

Ich muss auch die Kombination basierend auf anderen Werten aktivieren/deaktivieren.

Irgendeine Idee, wie ich das erreichen kann?

UPDATE 1:

Ok, ich habe einige Fortschritte gemacht, wo jetzt meine Trigger treten in aber aus irgendeinem Grund, wenn ich die Lage in meinem Drop-Down für die ausgewählte ändern (von Dusel!) Zelle ändert es den Wert für alle Zeilen auf denselben Wert.

Hier ist meine vollständige Code für die Drop-Down-Spalte:

<DataGridComboBoxColumn Header="Location" 
    SelectedItemBinding="{Binding DataContext.SelectedLineItem.SelectedLocation, 
    RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, 
    Mode=TwoWay}" 
    SelectedValuePath="LocationId" 
         DisplayMemberPath="LocationText" 
         TextBinding="{Binding Location, Mode=TwoWay}"> 
    <DataGridComboBoxColumn.ElementStyle> 
     <Style TargetType="{x:Type ComboBox}"> 
      <Setter Property="ItemsSource" Value="{Binding DataContext.Locations, 
      RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/> 
      <Setter Property="IsReadOnly" Value="True"/> 
      <Setter Property="FontSize" Value="14"/> 
     </Style> 
    </DataGridComboBoxColumn.ElementStyle> 
    <DataGridComboBoxColumn.EditingElementStyle> 
     <Style TargetType="{x:Type ComboBox}"> 
      <Setter Property="ItemsSource" Value="{Binding DataContext.Locations, 
      RelativeSource={RelativeSource FindAncestor, 
      AncestorType={x:Type Window}}}"/> 
      <Setter Property="SelectedItem" Value="{Binding DataContext.SelectedLocation, 
      RelativeSource={RelativeSource FindAncestor, 
      AncestorType={x:Type Window}}}"/> 
      <Setter Property="IsReadOnly" Value="False"/> 
      <Setter Property="IsEditable" Value="True"/> 
      <Setter Property="FontSize" Value="14"/> 
      <EventSetter Event="KeyUp" Handler="LocationColumn_KeyUp"></EventSetter> 
      <Style.Triggers> 
       <Trigger Property="IsKeyboardFocusWithin" Value="True"> 
        <Setter Property="IsDropDownOpen" Value="true" /> 
       </Trigger> 
      </Style.Triggers> 
     </Style> 
    </DataGridComboBoxColumn.EditingElementStyle> 
</DataGridComboBoxColumn> 

Und hier ist der vollständige Code für meine Checkbox Spalte (nicht um Sie kümmern, was die Auslöser tun - sie sind Test auslöst):

<DataGridCheckBoxColumn Header="Active" Binding="{Binding IsActive}"> 
    <DataGridCheckBoxColumn.CellStyle> 
     <Style TargetType="DataGridCell"> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding SelectedLocation.LocationId}" Value="1"> 
        <Setter Property="Background" Value="Green" /> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="" > 
        <Setter Property="IsEnabled" Value="False" /> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="01" > 
        <Setter Property="IsEnabled" Value="True" /> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="02" > 
        <Setter Property="IsEnabled" Value="False" /> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="03" > 
        <Setter Property="IsEnabled" Value="False" /> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </DataGridCheckBoxColumn.CellStyle> 
</DataGridCheckBoxColumn> 

Kann jemand herausfinden, warum alle meine Reihen jetzt eingestellt werden, wenn ich einen Wert in einer Kombination ändere?

Danke.

+0

Die Datacontext für die Bindung kann nicht sein, was Sie denken, es ist; Funktioniert es mit 'RelativeSource AncestorType = DataGrid'? –

+0

@EdPlunkett Ich habe meine Antwort aktualisiert. Habe weiter aber immer noch nicht 100% da. Irgendwelche Ideen? – Thierry

Antwort

0

Sie binden Ihr Kontrollkästchen an SelectedLineItem.Location. Aber ich kann sehen, dass diese Eigenschaft nirgends an das Kombinationsfeld gebunden ist. Sie haben die TextBinding Ihrer Combobox an "Location" gebunden. Versuchen Sie es auch in SelectedILineItem.Location zu ändern. Das Kontrollkästchen wird dann an den eingegebenen Wert in der Combobox gebunden. Wenn Sie das Kontrollkästchen abhängig vom ausgewählten Wert der Combobox aktivieren/deaktivieren möchten, sollten Sie den SelectedValuePath Ihrer Combobox an diese Eigenschaft binden oder die Checkbox-Bindung an SelectedItem.LocationId und die Triggerbedingung ändern, um der Bindung der Combobox zu entsprechen .

0

Wenn ich Ihre Frage richtig verstanden habe, denke ich, dass Sie dies auf diese Weise versuchen können. Ich habe eine Liste von Ländern in einem Kombinationsfeld gebunden und basierend auf der Auswahl eines Wertes habe ich die andere Spalte deaktiviert.

Der XAML-Code sieht aus wie

<Window.Resources> 
     <staticData:CountryList x:Key="CountryList"/> 
    </Window.Resources> 

    <Grid> 
     <DataGrid ItemsSource="{Binding SampleList}" AutoGenerateColumns="False"> 
      <DataGrid.Columns> 
       <DataGridTemplateColumn Header="Countries" Width="100"> 
        <DataGridTemplateColumn.CellTemplate> 
         <DataTemplate> 
          <TextBlock Text="{Binding SelectedCountry}"/> 
         </DataTemplate> 
        </DataGridTemplateColumn.CellTemplate> 

        <DataGridTemplateColumn.CellEditingTemplate> 
         <DataTemplate> 
          <ComboBox Height="22" Grid.Row="0" 
             ItemsSource="{StaticResource CountryList}" 
             SelectedItem="{Binding SelectedCountry}"> 
          </ComboBox> 
         </DataTemplate> 
        </DataGridTemplateColumn.CellEditingTemplate> 

       </DataGridTemplateColumn> 

       <!-- Inputs --> 
       <DataGridTextColumn Width="SizeToCells" Header="Inputs" MinWidth="100" Binding="{Binding Input}" > 
        <DataGridTextColumn.CellStyle> 
         <Style TargetType="DataGridCell"> 
          <Style.Triggers> 
           <DataTrigger Binding="{Binding SelectedCountry}" Value="UK"> 
            <Setter Property="IsEnabled" Value="false"/> 
           </DataTrigger> 
          </Style.Triggers> 
         </Style> 
        </DataGridTextColumn.CellStyle> 
       </DataGridTextColumn> 
      </DataGrid.Columns> 
     </DataGrid> 
    </Grid> 

Ansichtsmodell

public class MainViewModel : ObservableObject 
    { 
     private List<SampleData> sampleList; 

     public List<SampleData> SampleList 
     { 
      get { return sampleList; } 
      set { Set(ref sampleList, value); } 
     } 

     private Country selectedItem; 

     public Country SelectedItem 
     { 
      get { return selectedItem; } 
      set { selectedItem = value; } 
     } 

     private ObservableCollection<Country> countries; 

     public ObservableCollection<Country> CountriesList 
     { 
      get { return countries; } 
      set { this.Set(ref countries, value); } 
     } 

     public MainViewModel() 
     { 
      CountriesList = new ObservableCollection<Country> { new Country { Id = 1, Name = "India" }, new Country { Id = 1, Name = "Australia" } }; 

      SampleList = new List<SampleData> 
      { 
       new SampleData 
       { 
        Input = "shan", RowNum = 3, SelectedCountry = "India" 
       }, 

       new SampleData 
       { 
        Input = "raj", RowNum = 1, SelectedCountry = "India" 
       }, 

       new SampleData 
       { 
        Input = "sfk", RowNum = 9, SelectedCountry = "India" 
       }, 

       new SampleData 
       { 
        Input = "ShanSfk", RowNum = 7, SelectedCountry = "India" 
       } 
      }; 
     } 
    } 

hat und die Liste ist

public class CountryList : List<string> 
    { 
     public CountryList() 
     { 
      this.Add("India"); 
      this.Add("Australia"); 
      this.Add("UK"); 
     } 
    } 

Basierend auf der Auswahl des Landes in Combo-Box wird die Zelle aktiviert oder behindert.

+0

Vielen Dank, dass Sie sich die Zeit genommen haben, ein so detailliertes Beispiel zu liefern, aber Sie haben einen anderen Kontrolltyp für die Combo-Spalte verwendet, und während ich versucht habe, das zu integrieren, verbrachte ich mehr Zeit damit, dieses Problem zu lösen. Ich habe meine Antwort mit mehr Informationen aktualisiert, wenn das hilfreich ist. – Thierry

1

Dank @Freeman für das Zeigen in die richtige Richtung.

Ich fand es herauszufinden und die einzige Möglichkeit, es vollständig zum Laufen zu bringen, war eine Kombination aus Festlegen von Eigenschaften in XAML und Anwenden einiger grundlegender Logik in meinem ViewModel.

Hier ist die vollständige Erklärung:

ich ein DataGridComboBoxColumn habe, die meine SelectionLocation Eigenschaft binded und gehören zu meiner Reihe Ansichtsmodell

get { return this._selectedLocation; } 
set { Set(() => SelectedLocation, ref this._selectedLocation, value); } 

nun in Bezug auf die Bindung in XAML:

<DataGridComboBoxColumn Header="Location" 
    SelectedItemBinding="{Binding SelectedLocation, Mode=TwoWay}" 
    SelectedValuePath="LocationId" 
    DisplayMemberPath="LocationText"> 

Dies war mein erstes Problem, als ich jedes Mal, wenn ich ein Element aus der Combo auswählte, den Setter-Teil von SelectedLocation nicht aufrufen/auslösen konnte Ansichtsmodell Dies wurde behoben durch UpdateSourceTrigger=PropertyChanged Zugabe:

<DataGridComboBoxColumn Header="Warehouse" 
    SelectedItemBinding="{Binding SelectedLocation, Mode=TwoWay, 
          UpdateSourceTrigger=PropertyChanged}" 
    SelectedValuePath="LocationId" 
    DisplayMemberPath="LocationText"> 

In Bezug auf die Checkbox Spalte wurde die XAML definiert als:

<DataGridCheckBoxColumn Header="Active" Binding="{Binding IsActive, Mode=TwoWay> 
    <DataGridCheckBoxColumn.ElementStyle> 
     <Style TargetType="CheckBox"> 
      <Setter Property="HorizontalAlignment" Value="Center" /> 
      <Setter Property="VerticalAlignment" Value="Center" /> 
    </DataGridCheckBoxColumn.ElementStyle> 
</DataGridCheckBoxColumn> 

Auch bei der Überprüfung und meine Kontrollkästchen deaktivieren, es hat nicht auslösen den Setter meiner IsActive-Eigenschaft, die zu demselben ViewModel wie die Eigenschaft 'SelectedLocation' gehört.

um dieses Problem zu beheben, endete ich die UpdateSourceTrigger=PropertyChanged Aufsummierung:

<DataGridCheckBoxColumn Header="Active" Binding="{Binding IsActive, Mode=TwoWay, 
    UpdateSourceTrigger=PropertyChanged}"> 
    <DataGridCheckBoxColumn.ElementStyle> 
     <Style TargetType="CheckBox"> 
      <Setter Property="HorizontalAlignment" Value="Center" /> 
      <Setter Property="VerticalAlignment" Value="Center" /> 
    </DataGridCheckBoxColumn.ElementStyle> 
</DataGridCheckBoxColumn> 

Nun, da die Bindung Probleme mit der Combo und das Kontrollkästchen Spalten sortiert werden, ist eine Sache geblieben. Bedingte Auswahl Dies wurde mit einer Kombination von DataTrigger in XAML und Code in meinem ViewModel sortiert.

Die XAML kümmerten zu aktivieren/deaktivieren Sie das Kontrollkästchen, wie auf der Auswahl aus dem SelectedLocation:

<DataGridCheckBoxColumn Header="Active" Binding="{Binding IsActive, Mode=TwoWay, 
    UpdateSourceTrigger=PropertyChanged}"> 
    <DataGridCheckBoxColumn.ElementStyle> 
     <Style TargetType="CheckBox"> 
      <Setter Property="HorizontalAlignment" Value="Center" /> 
      <Setter Property="VerticalAlignment" Value="Center" /> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="01" > 
        <Setter Property="IsEnabled" Value="True" /> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="02" > 
        <Setter Property="IsEnabled" Value="False" /> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="03" > 
        <Setter Property="IsEnabled" Value="False" /> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </DataGridCheckBoxColumn.ElementStyle> 
</DataGridCheckBoxColumn> 

Und in meinem Viewmodel, wann immer der SelectedLocation Setter ausgelöst wird, es gilt jetzt die gleiche Regel also überprüfen, ob Standort ist 01, 02 oder 03, und es wird meine IsActive Eigenschaft und deshalb wählen/deaktivieren sie das Kontrollkästchen gesetzt:

public LocationViewModel SelectedLocation 
{ 
    get { return this._selectedLocation; } 
    set 
    { 
     Set(() => SelectedLocation, ref this._selectedLocation, value); 
     if (this._selectedLocation.LocationText == "01") 
      this.IsActive = false; 
     else if (this._selectedLocation.LocationText == "02") 
      this.IsActive = true; 
     else if (this._selectedLocation.LocationText == "03") 
     { 
      this.IsActive = false; 
     } 
    } 
} 

das ist offensichtlich nicht ideal ist, aber es funktioniert genau wie erwartet.Die ideale Lösung, unter einer Bedingung in XAML als solche IsChecked Satz wahr oder falsch zu haben, basierend gewesen wäre:

<DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="02" > 
<Setter Property="IsChecked" Value="True" /> 
<Setter Property="IsEnabled" Value="False" /> 
</DataTrigger> 

Aber aus welchem ​​Grund auch immer, wenn ich diese Methode verwenden, wird es die IsActive Setter auslösen, wenn ich überprüfen Das Kontrollkästchen wird manuell aktiviert, aber es wird nicht basierend auf den Triggerregeln ausgelöst, wodurch diese Eigenschaft nutzlos wird, die ich nicht haben kann.

Wie auch immer, ich denke das ist es. Hoffe das hilft anderen.

UPDATE

Ich hatte ein Update zu meiner Überraschung zu schreiben, während die Checkbox

<DataGridCheckBoxColumn Header="Active" Binding="{Binding IsActive, Mode=TwoWay, 
    UpdateSourceTrigger=PropertyChanged}"> 
    <DataGridCheckBoxColumn.ElementStyle> 
     <Style TargetType="CheckBox"> 
      <Setter Property="HorizontalAlignment" Value="Center" /> 
      <Setter Property="VerticalAlignment" Value="Center" /> 
      <Style.Triggers> 
       <DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="01" > 
        <Setter Property="IsEnabled" Value="True" /> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="02" > 
        <Setter Property="IsEnabled" Value="False" /> 
       </DataTrigger> 
       <DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="03" > 
        <Setter Property="IsEnabled" Value="False" /> 
       </DataTrigger> 
      </Style.Triggers> 
     </Style> 
    </DataGridCheckBoxColumn.ElementStyle> 
</DataGridCheckBoxColumn> 

Es ist nur vorübergehend deaktiviert deaktiviert werden. Ein Doppelklick auf die Zelle aktiviert die Zelle und aktiviert die Checkbox erneut! Völlig sinnlos, damit Sie ein Kontrollkästchen deaktivieren können, um es wieder zu aktivieren, wenn die Zelle in den Bearbeitungsmodus geht !!!

Wie auch immer, glücklicherweise gibt es eine Arbeit um die Zelle statt der Checkbox zu deaktivieren. Dies kann unter Verwendung des CellStyle anstelle des ElementStyle erreicht werden:

<DataGridCheckBoxColumn.CellStyle> 
    <Style TargetType="DataGridCell"> 
     <Style.Triggers> 
      <DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="01" > 
       <Setter Property="IsEnabled" Value="True" /> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="02" > 
       <Setter Property="IsEnabled" Value="False" /> 
      </DataTrigger> 
      <DataTrigger Binding="{Binding SelectedLocation.LocationText}" Value="03" > 
       <Setter Property="IsEnabled" Value="False" /> 
      </DataTrigger> 
     </Style.Triggers> 
    </Style> 
</DataGridCheckBoxColumn.CellStyle> 
Verwandte Themen