簡體   English   中英

交替行 colors 上的 LoadingRow 事件在 WPF DataGrid 加倍 colors 上的行

[英]Alternating row colors on LoadingRow event in WPF DataGrid doubling colors on rows

我通過 LoadingRow 事件以編程方式交替行 colors。 這樣做的原因是因為我需要在某些行上指定特定的顏色,即標記為刪除的行和帶有修改數據的行。

這工作正常,直到我在 DataGrid 中向上滾動並得到這個非常奇怪的交互,它使行 colors 增加一倍或三倍。

在此處輸入圖像描述

向下滾動時正確顯示。

我嘗試使用 AlternationIndex 並將 AlternationCount 設置為 2,並使用 bool 在兩者之間進行翻轉,兩者都會導致完全相同的問題。

如果我沒有在 LoadingRow 事件中設置它並使用 DataGrid AlternatingRowBackground,那么當我滾動表格時,行顏色會滲入其他行。

private void dataGrid_LoadingRow(object sender, DataGridRowEventArgs e)
        {
            // Get the DataRow corresponding to the DataGridRow that is loading.
            var item = e.Row.Item as ExpandoObject;
            if (loadedTable.ToDelete.Contains(item))
            {
                e.Row.Background = new SolidColorBrush(Colors.OrangeRed);
                return;
            }
            else if (loadedTable.Modified.Contains(loadedTable.Rows.IndexOf(item)))
            {
                e.Row.Background = new SolidColorBrush(Colors.LightYellow);
                return;
            }
            else if (e.Row.AlternationIndex == 0)
            {
                e.Row.Background = new SolidColorBrush(Colors.WhiteSmoke);
            }
            else if (e.Row.AlternationIndex == 1)
            {
                e.Row.Background = new SolidColorBrush(Colors.LightGray);
            }
        }
<DataGrid CanUserAddRows="False" GridLinesVisibility="All" VerticalGridLinesBrush="Gray" HorizontalGridLinesBrush="Gray"
                                 FontSize="15" FrozenColumnCount ="1" x:Name="xmlData" EnableRowVirtualization="True" AlternationCount="1"
                                 AlternatingRowBackground="LightGray" Background="WhiteSmoke"
                                 Grid.Column="1" Margin="0,-31,5,10" AutoGenerateColumns="False" Grid.Row="2" SelectionUnit="Cell" 
                                 PreviewKeyDown="DataGridKeyDown_Event" IsReadOnly="True" CanUserDeleteRows="True"
                                 LoadingRow="dataGrid_LoadingRow"/>

您遇到的問題是因為 DataGrid 重用了 DataGridRow 對象(可以嘗試 EnableRowVirtualization="False")。

您要做的是使用 styles 根據其數據/項目設置 DataGridRow 的背景。

這是一個測試應用程序,可以執行您想做的事情。

XAML

<Window x:Class="WpfApp9.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:WpfApp9"
    mc:Ignorable="d"
    Title="MainWindow" Height="450" Width="800">
<Window.DataContext>
    <local:VM />
</Window.DataContext>
<Grid>
    <DataGrid AutoGenerateColumns="False" ItemsSource="{Binding Items}" AlternationCount="2">
        <DataGrid.Resources>
            <!-- Converter used to convert the DataRow's Item and the VM.ToDelete list to bool (true = it is deleted) -->
            <local:IsDeletedConverter x:Key="IsDeletedConverter" />
        </DataGrid.Resources>
        <DataGrid.RowStyle>
            <Style TargetType="DataGridRow">
                <Style.Triggers>
                    <!-- Setup the background color for normal rows using AlternationIndex -->
                    <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                        <Setter Property="Background" Value="WhiteSmoke" />
                    </Trigger>
                    <Trigger Property="ItemsControl.AlternationIndex" Value="1">
                        <Setter Property="Background" Value="LightGray" />
                    </Trigger>
                    <!-- Override the above background colors if it is in the deleted list - NOTE: these styles are processed in order, make sure this is after the above triggers -->
                    <DataTrigger Value="True">
                        <DataTrigger.Binding>
                            <MultiBinding Converter="{StaticResource IsDeletedConverter}">
                                <!-- This is the DataContext of the DataGridRow - the item (ExpandoObject) we will check for in the deleted list -->
                                <Binding />
                                <!-- Need the deleted list, which is in VM -->
                                <Binding RelativeSource="{RelativeSource AncestorType=Window}" Path="DataContext" />
                            </MultiBinding>
                        </DataTrigger.Binding>
                        <DataTrigger.Setters>
                            <Setter Property="Background" Value="OrangeRed" />
                        </DataTrigger.Setters>
                    </DataTrigger>
                </Style.Triggers>
            </Style>
        </DataGrid.RowStyle>
        <DataGrid.Columns>
            <DataGridTextColumn Header="Col1" Binding="{Binding Col1}" />
            <DataGridTextColumn Header="Col2" Binding="{Binding Col2}" />
        </DataGrid.Columns>
    </DataGrid>
</Grid>

代碼

using System;
using System.Collections.Generic;
using System.Globalization;
using System.Windows;
using System.Windows.Data;

namespace WpfApp9
{
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }
    }

    public class VM
    {
        public List<System.Dynamic.ExpandoObject> Items { get; set; }
        public List<System.Dynamic.ExpandoObject> ToDelete { get; set; }

        public VM()
        {
            Items = new List<System.Dynamic.ExpandoObject>();
            ToDelete = new List<System.Dynamic.ExpandoObject>();

            for (int i = 0; i < 1000; i++)
            {
                var eo = new System.Dynamic.ExpandoObject();
                var d = eo as IDictionary<string, object>;
                d["Col1"] = $"String {i}";
                d["Col2"] = i;
                Items.Add(eo);

                // Add some items to ToDelete list
                if (i % 10 == 0)
                {
                    ToDelete.Add(eo);
                }
            }
        }
    }

    public class IsDeletedConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            if (values.Length != 2)
                throw new ArgumentException($"IsDeletedConverter is expecting 2 values but got {values.Length} values!", nameof(values));

            if (values[0] is System.Dynamic.ExpandoObject eo && values[1] is VM vm)
            {
                if (vm.ToDelete.Contains(eo))
                    return true;
            }
            return false;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM