ScrollIntoView不会滚动到DataGrid中的SelectedItem

时间:2018-10-12 15:54:21

标签: c# .net wpf user-interface

我正在使用模型来选择DataGrid中的项,如下所示:

public ObservableCollection<MyModel> Models{
   get {return m_Models; }
}

public MyModel SelectedModel
{
   get{ return m_SelectedModel; }
   set{
        m_SelectedModel = value;
    }
    NotifyPropertyChanged("SelectedModel");
    NotifyPropertyChanged("Models");
}

这两个公共属性在模型中,即窗口的数据上下文。在XAML中,Observable Collection绑定到数据网格,SelectedItem绑定到SelectedModel:

<DataGrid x:Name="MyDataGrid" AutoGenerateColumns="False" IsReadOnly="True" CanUserResizeColumns="True" CanUserAddRows="False" CanUserSortColumns="True"
                                  SelectionMode="Single" SelectionChanged="DataGrid_SelectionChanged" ItemsSource="{Binding Models}"
                                  CanUserResizeRows="False" IsTextSearchEnabled="True" RowHeaderWidth="0" SelectedItem="{Binding SelectedModel, Mode=TwoWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True}" Grid.ColumnSpan="2" Margin="0,0,-0.4,-0.4">

因此,每当我更改SelectedModel时,数据网格中的SelectedItem都会更新。这工作得很好,我已经能够基于SelectedItem填充其他数据。确实,在设置SelectedModel时会调用我的DataGrid_SelectionChanged事件处理程序。

但是,每当我选择一个新项目时,我都希望数据网格自动滚动以显示SelectedItem。我尝试了多种方法使它正常工作,但无济于事。这是我尝试过的一些事情(已确认此功能已通过调试器调用):

    private void DataGrid_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        if(MyDataGrid.SelectedItem != null)
        {
           //All 3 of these have been tried separately and do not work
           MyDataGrid.ScrollIntoView(MyDataGrid.SelectedItem);
           MyDataGrid.ScrollIntoView(MyDataGrid.Items[MyDataGrid.SelectedIndex]);
           MyDataGrid.ScrollIntoView(_model.SelectedModel); //Didn't expect this one to work but just want to show that I'm trying things out here
        }
    }

我已经查看了ScrollIntoView的其他问题,但似乎都无法解决我的问题。我将不胜感激。谢谢。

2 个答案:

答案 0 :(得分:0)

不知道为什么它对您不起作用,但是它肯定可以正常工作。在下面查看演示应用程序代码:

XAML

<Window x:Class="WpfApplication1.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:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525">

    <Grid>
        <DataGrid x:Name="MyDataGrid" AutoGenerateColumns="False" IsReadOnly="True" CanUserResizeColumns="True" CanUserAddRows="False" CanUserSortColumns="True"
                  SelectionMode="Single" SelectionChanged="DataGrid_SelectionChanged" ItemsSource="{Binding Items}"
                  CanUserResizeRows="False" IsTextSearchEnabled="True" RowHeaderWidth="0" SelectedItem="{Binding SelectedItem, Mode=TwoWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True}"
                  Grid.ColumnSpan="2" Margin="0,0,-0.4,-0.4">
            <DataGrid.Resources>
                <SolidColorBrush x:Key="{x:Static SystemColors.HighlightBrushKey}" Color="Red" />
                <SolidColorBrush x:Key="{x:Static SystemColors.InactiveSelectionHighlightBrushKey }" Color="Red" />
            </DataGrid.Resources>
            <DataGrid.Columns>
                <DataGridTextColumn Header="Id" Binding="{Binding Id}" />
                <DataGridTextColumn Header="Name" Binding="{Binding Name}" />
            </DataGrid.Columns>
        </DataGrid>
    </Grid>
</Window>

类文件

using System;
using System.ComponentModel;
using System.Linq;
using System.Timers;
using System.Windows;

namespace WpfApplication1
{
    public class Model
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }

    public class ViewModel : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        private readonly Model[] items;

        public ViewModel()
        {
            items = Enumerable.Range(1, 101)
                              .Select(x => new Model
                              {
                                  Id = x,
                                  Name = $"Item {x}"
                              })
                              .ToArray();
        }

        public Model[] Items => items;

        private Model selectedItem;
        public Model SelectedItem
        {
            get { return selectedItem; }
            set
            {
                selectedItem = value;
                PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(SelectedItem)));
            }
        }

    }

    public partial class MainWindow : Window
    {
        private readonly Timer timer;
        private readonly ViewModel model;
        private readonly Random random;

        public MainWindow()
        {
            InitializeComponent();
            model = new ViewModel();
            random = new Random();
            timer = new Timer(2000);

            DataContext = model;

            timer.Elapsed += Timer_Elapsed;
            timer.Start();
        }

        private void Timer_Elapsed(Object sender, ElapsedEventArgs e)
        {
            var index = random.Next(model.Items.Length);
            model.SelectedItem = model.Items[index];
        }

        private void DataGrid_SelectionChanged(Object sender, System.Windows.Controls.SelectionChangedEventArgs e)
        {
            if (MyDataGrid.SelectedItem != null)
            {
                MyDataGrid.ScrollIntoView(MyDataGrid.SelectedItem);
            }
        }

        protected override void OnClosing(CancelEventArgs e)
        {
            base.OnClosing(e);

            timer.Stop();
            timer.Dispose();
        }
    }
}

在我看来,您的代码正在执行某些操作,可能会阻止框架滚动网格。

答案 1 :(得分:0)

我能够使ScrollIntoView工作,但是我需要将ScrollToView函数放入数据网格的Loaded回调中。以下是解决此问题的示例:

    private void DataGrid_Loaded(object sender, RoutedEventArgs e)
    {
        if(MyDataGrid.SelectedItem != null)
        {
            MyDataGrid.ScrollIntoView(MyDataGrid.SelectedItem);
        }
    }

我的猜测是数据网格没有完全加载到SelectionChanged事件上,因此没有滚动到正确的位置。