I am using a Model to select an item in a DataGrid like so:
public ObservableCollection<MyModel> Models{
get {return m_Models; }
}
public MyModel SelectedModel
{
get{ return m_SelectedModel; }
set{
m_SelectedModel = value;
}
NotifyPropertyChanged("SelectedModel");
NotifyPropertyChanged("Models");
}
Those two public properties are in a model that is the data context of the window. The Observable Collection is bound to the data grid and SelectedItem is bound to SelectedModel like so in 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">
So, whenever I change the SelectedModel, the SelectedItem in the data grid is updated. This works just fine and I've been able to populate other data based off of the SelectedItem. Indeed, my DataGrid_SelectionChanged event handler gets called upon setting the SelectedModel.
However, whenever I select a new item, I would like the data grid to automatically scroll to show the SelectedItem. I've tried multiple ways to get this to work but to no avail. Here are a few things I've tried (this function is confirmed getting called with debugger):
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
}
}
I have looked around at other issues with ScrollIntoView and none seem to solve my problem. I'd appreciate any help that would be offered. Thank you.
Not sure why it is not working for you, but it certainly works without any issue. Check out demo application code below:
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>
Class Files
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();
}
}
}
To me it seems, your code is doing something which may be preventing framework from scrolling the grid.
I was able to get ScrollIntoView working but I needed to put the ScrollToView function in the Loaded callback for the data grid. Here's a sample of what fixed the issue:
private void DataGrid_Loaded(object sender, RoutedEventArgs e)
{
if(MyDataGrid.SelectedItem != null)
{
MyDataGrid.ScrollIntoView(MyDataGrid.SelectedItem);
}
}
My guess is that the data grid wasn't fully loaded on the SelectionChanged event and as such, was not scrolling to the proper location.
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.