So legen Sie den Zeilenhintergrund von DataGrid basierend auf einem Eigenschaftswert mithilfe von Datenbindungen fest

81

In meinem XAML-Code möchte ich die BackgroundFarbe jeder Zeile basierend auf einem Wert des Objekts in einer bestimmten Zeile festlegen . Ich habe eine ObservableCollectionvon z, und jede von zhat eine Eigenschaft namens State. Ich begann mit so etwas in meinem DataGrid:

<DataGrid.RowStyle>
    <Style TargetType="DataGridRow">
        <Setter Property="Background" 
                Value="{Binding z.StateId, Converter={StaticResource StateIdToColorConverter}}"/>
     </Style>
</DataGrid.RowStyle>

Dies ist ein falscher Ansatz, da x keine Eigenschaft in meiner ViewModel-Klasse ist.

In meiner Klasse Viewmodel habe ich eine , ObservableCollection<z>die das ist ItemsSourcedieser DataGrid, und ein SelectedItemTyp z.

Ich könnte die Farbe binden SelectedItem, aber dies ändert nur eine Zeile in der DataGrid.

Wie kann ich basierend auf einer Eigenschaft die Hintergrundfarbe dieser Zeilen ändern?

Tobias Moe Thorstensen
quelle

Antworten:

168

Verwenden Sie ein DataTrigger:

<DataGrid ItemsSource="{Binding YourItemsSource}">
    <DataGrid.RowStyle>
        <Style TargetType="DataGridRow"> 
            <Style.Triggers>
                <DataTrigger Binding="{Binding State}" Value="State1">
                    <Setter Property="Background" Value="Red"></Setter>
                </DataTrigger>
                <DataTrigger Binding="{Binding State}" Value="State2">
                    <Setter Property="Background" Value="Green"></Setter>
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </DataGrid.RowStyle>
</DataGrid>
Nitesh
quelle
2
Ich erhalte nur: BindingExpression-Pfadfehler: 'State' property not found on 'object' ''z' (HashCode=7162954)'. BindingExpression:Path=State; DataItem='z' (HashCode=7162954); target element is 'DataGridRow' (Name=''); target property is 'NoTarget' (type 'Object')Wie kommt es, dass der Eigenschaftsstatus nicht gefunden wird, wenn meine Entität dies enthält und meine Datenbank den Status als Spalte anzeigt?
Tobias Moe Thorstensen
2
Ich hoffe du machst es nicht so z.State.
Nitesh
4
Bin gerade nach einer Pause von wpf wieder darauf gestoßen, wünschte ich könnte wieder upvoten!
Ric
5
Das ist toll. In der Lösung, in der ich es verwendet habe, musste sich der Status basierend auf einem enumWert ändern . Diese Antwort auf StackOverflow hat mir dabei geholfen.
Kaspermoerch
Vergessen Sie nicht, dass die Eigenschaft, an die Sie binden, sein musspublic
CAD-Typ
17

Das gleiche kann auch ohne gemacht DataTriggerwerden:

 <DataGrid.RowStyle>
     <Style TargetType="DataGridRow">
         <Setter Property="Background" >
             <Setter.Value>
                 <Binding Path="State" Converter="{StaticResource BooleanToBrushConverter}">
                     <Binding.ConverterParameter>
                         <x:Array Type="SolidColorBrush">
                             <SolidColorBrush Color="{StaticResource RedColor}"/>
                             <SolidColorBrush Color="{StaticResource TransparentColor}"/>
                         </x:Array>
                     </Binding.ConverterParameter>
                 </Binding>
             </Setter.Value>
         </Setter>
     </Style>
 </DataGrid.RowStyle>

Wo BooleanToBrushConverterist die folgende Klasse:

public class BooleanToBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value == null)
            return Brushes.Transparent;

        Brush[] brushes = parameter as Brush[];
        if (brushes == null)
            return Brushes.Transparent;

        bool isTrue;
        bool.TryParse(value.ToString(), out isTrue);

        if (isTrue)
        {
            var brush =  (SolidColorBrush)brushes[0];
            return brush ?? Brushes.Transparent;
        }
        else
        {
            var brush = (SolidColorBrush)brushes[1];
            return brush ?? Brushes.Transparent;
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
Vahagn Nahapetyan
quelle
Noch besser ist die Anwendung eines IMultiValueConverter ( docs.microsoft.com/en-us/dotnet/api/… ), um einfach mehr als eine Eigenschaft zu binden und den Konverter die richtige Farbe für den Status dieser mehreren Eigenschaften zurückgeben zu lassen (ich ommit das Beispiel, da es dem normalen Konvertergehäuse wirklich ähnlich ist, aber ich kann es posten, falls jemand es braucht)
user8276908
7

Fügen Sie in XAML eine RowStyle-Eigenschaft für das DataGrid hinzu und definieren Sie sie mit dem Ziel, den Hintergrund der Zeile auf die in meinem Mitarbeiterobjekt definierte Farbe festzulegen.

<DataGrid AutoGenerateColumns="False" ItemsSource="EmployeeList">
   <DataGrid.RowStyle>
        <Style TargetType="DataGridRow">
             <Setter Property="Background" Value="{Binding ColorSet}"/>
        </Style>
   </DataGrid.RowStyle>

Und in meiner Mitarbeiterklasse

public class Employee {

    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }

    public string ColorSet { get; set; }

    public Employee() { }

    public Employee(int id, string name, int age)
    {
        Id = id;
        Name = name;
        Age = age;
        if (Age > 50)
        {
            ColorSet = "Green";
        }
        else if (Age > 100)
        {
            ColorSet = "Red";
        }
        else
        {
            ColorSet = "White";
        }
    }
}

Auf diese Weise hat jede Zeile des DataGrid die Hintergrundfarbe der ColorSet Eigenschaft meines Objekts .

NICK_WANTED
quelle
Ich mag diese Methode, da die Farbe des Objekts im Modell selbst anstelle der Ansicht zentralisiert ist.
ΩmegaMan
1
Nur dass dies gegen MVVM verstößt. Wenn es Sie nicht interessiert, haben Sie es. Die Benutzererfahrung sollte jedoch nicht vom Modell bestimmt werden. Das ist die Aufgabe von View / View Model
BrianVPS