如何在DataGrid中选择第一行并对数据进行排序我正在使用Wpf MVVM中的CollectionViewSource

qfe3c7zg  于 2023-02-05  发布在  其他
关注(0)|答案(1)|浏览(120)

我正在使用MVVM模型开发WPF应用程序,我使用的DataGrid有3列,第二列是datatime列。在DataGrid中,我希望将最后添加的记录显示为第一行,表示按降序排列,因此我使用CollectionViewSource并根据第二列对数据进行排序。这里的问题是,当网格行数增加时,滚动条会自动出现,但它不会向上移动,因此第一行不会显示,每次插入新行后记录我想手动滚动滚动条到顶部,这对客户来说也很烦人
下面是代码,

var collectionView = CollectionViewSource.GetDefaultView(this.GridDataSource);
collectionView.SortDescriptions.Add(new SortDescription("CreatedAt", ListSortDirection.Descending));
collectionView.Refresh();

在XAML中,我在DataGrid中使用了selectedIndex = 0,当我们启动应用程序时,这将起作用,但在插入新记录后,所选行不会更改,但在这里我希望选择新插入的行,

<DataGrid AutoGenerateColumns="False" SelectedIndex="0"
  ItemsSource="{Binding Path=Commands}" >

我尝试添加一个属性并绑定到selectedIndex,但仍然是同一个问题,但当我调试代码时,我发现selectedIdex值在添加新记录后不久即从0变为1,从1变为2,但在网格中,这些添加的数据存在,我需要手动向上滚动才能看到添加的行。

<DataGrid SelectedIndex="{Binding selectedRow}" >

执行以下代码后,SelectedIndex值表示selectedRow值从0更改为1,依此类推

this.GridDataSource.Add("FirstColumn",datetime.now,"Thirdcolumn");

在简单中,我想选择网格的第一行。
先谢了

xmakbtuz

xmakbtuz1#

您需要清除以前的排序,否则可能只是添加了越来越多的排序说明。

var collectionView = 
 CollectionViewSource.GetDefaultView(this.GridDataSource);
 collectionView.SortDescriptions.Clear(); 

 collectionView.SortDescriptions.Add(new SortDescription("CreatedAt", ListSortDirection.Descending));
 collectionView.Refresh();

您可以通过集合视图间接操作所选项。事实上,您可能必须这样做才能获得排序后的第一个项。在数据网格上:

<DataGrid ...
     IsSynchronizedWithCurrentItem="True"

然后,您可以使用collectionview选择第一个:

collectionView.MoveCurrentToFirst();

因为数据网格上的设置会尝试选中第一个项目。当然,它可以被虚拟化,所以那里没有UI可供选择。你需要调用scrollintoview。

datagrid.ScrollIntoView(datagrid.SelectedItem);

我使用一个行为:

class ScrollDataGridRowIntoView : Behavior<DataGrid>
{
    protected override void OnAttached()
    {
        
        base.OnAttached();
        this.AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
    }

    void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if (sender is DataGrid)
        {
            DataGrid datagrid = (sender as DataGrid);
            if (datagrid.SelectedItem != null)
            {
                datagrid.Dispatcher.BeginInvoke( (Action)(() => 
                    {
                        datagrid.UpdateLayout();
                        if (datagrid.SelectedItem !=  null)
                        { 
                            datagrid.ScrollIntoView(datagrid.SelectedItem);
                        }
                    }));
            }
        }
    }
    protected override void OnDetaching()
    {
        base.OnDetaching();
        this.AssociatedObject.SelectionChanged -=  AssociatedObject_SelectionChanged;
    }
}

选择行不会使其变为蓝色。您可能对其他行为感兴趣

class DataGridRowBehavior : Behavior<DataGridRow>
{
    public static bool GetIsDataGridRowFocussedWhenSelected(DataGridRow dataGridRow)
    {
        return (bool)dataGridRow.GetValue(IsDataGridRowFocussedWhenSelectedProperty);
    }

    public static void SetIsDataGridRowFocussedWhenSelected(
      DataGridRow dataGridRow, bool value)
    {
        dataGridRow.SetValue(IsDataGridRowFocussedWhenSelectedProperty, value);
    }

    public static readonly DependencyProperty IsDataGridRowFocussedWhenSelectedProperty =
        DependencyProperty.RegisterAttached(
        "IsDataGridRowFocussedWhenSelected",
        typeof(bool),
        typeof(DataGridRowBehavior),
        new UIPropertyMetadata(false, OnIsDataGridRowFocussedWhenSelectedChanged));

    static void OnIsDataGridRowFocussedWhenSelectedChanged(
      DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        DataGridRow item = depObj as DataGridRow;
        if (item == null)
            return;

        if (e.NewValue is bool == false)
            return;

        if ((bool)e.NewValue)
            item.Selected += OndataGridRowSelected;
        else
            item.Selected -= OndataGridRowSelected;
    }
    static void OndataGridRowSelected(object sender, RoutedEventArgs e)
    {
        DataGridRow row = e.OriginalSource as DataGridRow;
        // If focus is already on a cell then don't focus back out of it
        if (!(Keyboard.FocusedElement is DataGridCell) && row != null)
        {
            row.Focusable = true;
            Keyboard.Focus(row);
        }
    }
}

显然,这适用于datagridrow

<DataGrid.RowStyle>
            <Style TargetType="{x:Type DataGridRow}">
                <Setter Property="support:DataGridRowBehavior.IsDataGridRowFocussedWhenSelected" Value="true"/>
            </Style>
        </DataGrid.RowStyle>

相关问题