在WPF数据网格中排序事件后,依赖属性不起作用

本文关键字:依赖 属性 不起作用 事件 排序 数据 WPF 数据网 网格 | 更新日期: 2023-09-27 17:49:38

我有一个WPF数据网格,它有一个依赖属性。我使用MVVM和WPF数据网格绑定到一个可观察集合。网格保存搜索结果。当单击搜索按钮时,我从数据库中检索数据,填充可观察集合,然后填充网格。所有的好!在'search button click'方法的最后一行,我将依赖属性更新为true,这将触发依赖属性。依赖属性类中的代码将格式化数据网格(比如在某些单元格上设置边框,并确保重复的数据只显示一次)。

当一个业务需求是能够通过单击列标题进行排序时,我的问题就开始了。使用wpf数据网格的默认排序会导致网格失去格式,因此我创建了自己的排序处理程序,并在最后设置e.handled = true来禁用wpf数据网格控件的默认排序。还是很好!

问题现在出现了。如果我通过单击搜索按钮进行新的搜索,网格中的结果将被显示,但没有被格式化!我在依赖代码中设置了一个断点,发现在这个实例中断点没有被击中。

所以我的问题是……排序中的代码(我在下面包括)是否以某种方式破坏了依赖属性与数据网格的绑定?我想提请您注意我清除集合并重新填充它的代码。我是否应该以不同的方式实现排序,以避免出现这种行为?

排序处理程序中的代码。

void fg_Sorting(object sender, DataGridSortingEventArgs e) {
        System.Windows.Controls.DataGrid dg = sender as System.Windows.Controls.DataGrid;
        if (dg == null) {
            return;
        }
        DataGridMergeCellBehavior.SetIsMerged(dg, false);
        ObservableCollection<AssetPPM2GridEntity> source = dg.ItemsSource as ObservableCollection<AssetPPM2GridEntity>;
        List<AssetPPM2GridEntity> myList = source.OrderBy(x => x.Property).ToList();
        source.Clear();
        foreach (var item in myList) {
            source.Add(item);
        }
// This property below is the dependency property which formats the grid.
        DataGridMergeCellBehavior.SetIsMerged(dg, true);
        e.Handled = true;
    }
如果你需要更多的信息,请告诉我。我只是从你的经验中寻找可能解释这种行为的原因,我可以进一步调查。

下面是依赖属性的代码。

public class DataGridMergeCellBehavior : DependencyObject
{
    private static bool inUse = false;
    public static readonly System.Windows.DependencyProperty IsMergedProperty = System.Windows.DependencyProperty.RegisterAttached("IsMerged", typeof(bool), typeof(DataGridMergeCellBehavior), new PropertyMetadata(false, IsMergedChanged));

    public static bool GetIsMerged(DataGrid grid) {
        return (bool)grid.GetValue(IsMergedProperty);
    }
    public static void SetIsMerged(DataGrid grid, bool value) {
        grid.SetValue(IsMergedProperty, value);
    }
    private static void dg_ScrollChanged(object sender, ScrollChangedEventArgs e) {
        if (e.VerticalChange != 0 && !inUse) {
            inUse = true;
            DataGrid dataGrid = sender as DataGrid;
            int visibleRows = 0;
            int firstVisibleRowIndex = 0;
            foreach (var Item in dataGrid.Items) {
                var Row = (DataGridRow)dataGrid.ItemContainerGenerator.ContainerFromItem(Item);
                if (Row != null && Row.IsVisible) {
                    if (visibleRows == 0) {
                        firstVisibleRowIndex = Convert.ToInt32(Math.Floor(e.VerticalOffset));
                    }
                    visibleRows++;
                }
            }
            MergeDataGrid(dataGrid, visibleRows, firstVisibleRowIndex);
            inUse = false;
        }
    }
    private static void IsMergedChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e) {
        DataGrid dg = obj as DataGrid;
        if (dg != null) {
            int rowCount = dg.Items.Count;
            if (rowCount > 100) {
                rowCount = 100; // Why process the entire grid when not more than 100 will be shown to the user. 
            }
            if (dg.Columns.Count > 0 && (bool)e.NewValue) {
                dg.UpdateLayout();
                MergeDataGrid(dg, rowCount, 0);
            }
            else {
                if (dg.Columns.Count == 0) {
                    dg.Loaded += AssociatedObjectLoaded;
                    //dg.LoadingRow += OnLoadingRow;
                    //dg.UnloadingRow += OnUnloadingRow;
                    //dg.MouseLeftButtonDown += AssociatedObjectMouseLeftButtonUp;
                }
                MergeDataGrid(dg, rowCount, 0);
            }                
        }
    }
    static void AssociatedObjectLoaded(object sender, RoutedEventArgs e) {
        DataGrid grid = sender as DataGrid;
        grid.RemoveHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(dg_ScrollChanged));
        grid.AddHandler(ScrollViewer.ScrollChangedEvent, new ScrollChangedEventHandler(dg_ScrollChanged));
    }
    private static void MergeDataGrid(DataGrid grid, int visibleRows, int firstVisibleRowIndex) {
        // Code which will format cells with borders and delete cell content if its the same.
    }

这是我的数据网格XAML。

<DataGrid TabIndex="8" x:Name="fg" Grid.Row="7" Grid.Column="0" Grid.ColumnSpan="4" Margin="5" RowHeaderWidth="0"  ContextMenu="{StaticResource menuContext}"
              ItemsSource="{Binding AssetPPM2GridEntityCollection}" ColumnHeaderStyle="{StaticResource ColumnContextMenus}" HeadersVisibility="{Binding HeaderVisibility}"
              SelectedIndex="{Binding GrdFgSelectedIndex}" AutoGenerateColumns="False" SelectionUnit="FullRow"  SelectionMode="Extended"
              EnableRowVirtualization="True" EnableColumnVirtualization="False" RowBackground="PapayaWhip"
              VirtualizingPanel.VirtualizationMode="Standard" CanUserReorderColumns="False" 
              CanUserAddRows="False" GridLinesVisibility="Vertical" CanUserSortColumns="True" CanUserResizeColumns="False"                 
              dp:DataGridMergeCellBehavior.IsMerged="{Binding Source={StaticResource assetPPM2ViewModel}, Path=IsMergeCellsChecked, UpdateSourceTrigger=PropertyChanged}"
              PreviewMouseWheel="fg_PreviewMouseWheel" >

排序处理程序驻留在视图后面的代码中。

在WPF数据网格中排序事件后,依赖属性不起作用

感谢大家的评论。我张贴的答案,如果有人应该偶然发现这个或类似的问题。

问题是由这行代码引起的。

// This property below is the dependency property which formats the grid.
    DataGridMergeCellBehavior.SetIsMerged(dg, true);

直接设置依赖属性导致不一致的行为。我仍然不知道这背后的确切技术原因。

解决方案是获得ViewModel的实例,然后设置绑定到依赖属性的ViewModel的属性(为TRUE)。