【问题标题】:ScrollIntoView Does Not Scroll To SelectedItem in DataGridScrollIntoView 不会滚动到 DataGrid 中的 SelectedItem
【发布时间】:2019-03-17 21:28:10
【问题描述】:

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

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

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

这两个公共属性位于作为窗口数据上下文的模型中。 Observable Collection 绑定到数据网格,SelectedItem 绑定到 SelectedModel,就像在 XAML 中一样:

<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 填充其他数据。事实上,我的 DataGrid_SelectionChanged 事件处理程序会在设置 SelectedModel 时被调用。

但是,每当我选择一个新项目时,我希望数据网格自动滚动以显示 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 的其他问题,但似乎没有一个可以解决我的问题。我将不胜感激将提供的任何帮助。谢谢。

【问题讨论】:

    标签: c# .net wpf user-interface


    【解决方案1】:

    不知道为什么它不适合你,但它确实可以正常工作。查看下面的演示应用程序代码:

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

    在我看来,您的代码正在做一些可能会阻止框架滚动网格的事情。

    【讨论】:

      【解决方案2】:

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

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

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

      【讨论】:

        猜你喜欢
        • 2019-03-02
        • 2016-03-05
        • 2013-06-21
        • 2022-10-18
        • 2012-03-28
        • 2019-05-13
        • 1970-01-01
        • 2021-06-16
        • 1970-01-01
        相关资源
        最近更新 更多