Cách đặt Nền hàng của DataGrid, dựa trên giá trị thuộc tính bằng cách sử dụng liên kết dữ liệu


81

Trong mã XAML của mình, tôi muốn đặt Backgroundmàu của từng hàng, dựa trên giá trị của đối tượng trong một hàng cụ thể. Tôi có một ObservableCollectioncủa z, và mỗi trong số đó zcó một thuộc tính được gọi là State. Tôi bắt đầu với một cái gì đó như thế này trong DataGrid:

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

Đây là một cách tiếp cận sai vì x không phải là một thuộc tính trong lớp ViewModel của tôi.

Trong lớp ViewModel của tôi, tôi có một ObservableCollection<z>loại ItemsSourcenày DataGrid, và một SelectedItemloại z.

Tôi có thể liên kết màu với SelectedItem, nhưng điều này sẽ chỉ thay đổi một hàng trong DataGrid.

Làm cách nào để tôi có thể, dựa trên một thuộc tính thay đổi màu nền của hàng này?

Câu trả lời:


168

Sử dụng một 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>

2
Tôi chỉ nhận được: Lỗi đường dẫn BindingExpression: Làm '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')thế nào để nó không tìm thấy Trạng thái thuộc tính khi thực thể của tôi giữ điều này và cơ sở dữ liệu của tôi hiển thị Trạng thái dưới dạng cột?
Tobias Moe Thorstensen

2
Tôi hy vọng bạn không làm như vậy z.State.
Nitesh

4
Tôi chỉ gặp lại điều này sau một thời gian nghỉ từ wpf, ước gì tôi có thể ủng hộ một lần nữa!
Ric

5
Điều đó thật tuyệt. Trong giải pháp mà tôi đã sử dụng nó, tôi cần trạng thái thay đổi dựa trên một enumgiá trị. Câu trả lời này trên StackOverflow đã giúp tôi điều đó.
kaspermoerch

Đừng quên các tài sản mà bạn liên kết với có đượcpublic
CAD bloke

17

Điều tương tự cũng có thể được thực hiện mà không cần DataTrigger:

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

Trong trường hợp BooleanToBrushConverterlà lớp sau:

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();
    }
}

Thậm chí tốt hơn là việc áp dụng IMultiValueConverter ( docs.microsoft.com/en-us/dotnet/api/… ) để liên kết đơn giản nhiều thuộc tính và yêu cầu trình chuyển đổi trả về màu chính xác cho trạng thái của nhiều thuộc tính đó (tôi bỏ qua mẫu kể từ khi nó thực sự giống với trường hợp chuyển đổi bình thường nhưng tôi có thể gửi nó nên bất cứ ai cần nó)
user8276908

7

Trong XAML, hãy thêm và xác định Thuộc tính RowStyle cho DataGrid với mục tiêu đặt Nền của Hàng thành Màu được xác định trong Đối tượng Nhân viên của tôi.

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

Và trong Lớp nhân viên của tôi

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";
        }
    }
}

Bằng cách này, mỗi Hàng của DataGridMàu BackGround của ColorSet Thuộc tính của Đối tượng của tôi .


Tôi thích phương pháp này vì màu sắc của đối tượng được tập trung trong chính mô hình thay vì chế độ xem.
ΩmegaMan

1
Ngoại trừ việc điều này vi phạm MVVM. Nếu bạn không quan tâm, hãy có nó. Nhưng trải nghiệm người dùng không nên được xác định bởi mô hình. Đó là công việc của View / View Model
BrianVPS
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.