ScrollIntoView with nested ScrollViewer
In my application I have an Canvas wrapped in an ScrollViewer (Canvas is bigger then the screen size). On this canvas I have placed other controls. One of the elements on the canvas contains an virtualized DataGrid (with 2000+ rows ... so ther is scrolling involved as well). Now I have a function that is selecting a row in the DataGrid based on some values of the row element (triggered automaticaly). When the row is selected, I call
uxDataGrid.ScrollIntoView(uxDataGrid.SelectedItems[0]);
what is working perfectly fine. As a matter of fact it is working way to good. What I want, is that the element in the DataGrid is selected and then the DataGrid should scroll to the correct position. But also my Canvas scrolviewer is somehow picking up this request and is scrolling there as well.
I already tried to intercept the ScrollChangedEvent and set the handled flag. But it is not working.
Qustions:
1) How can I limit the effect of the ScrollIntoView call to the local user control.
2) If that is not possible, how can I do the scrolling by myself? I would need to calculate the vertical offset for the scrollviewer, but since it is virtualized I have no idea how I can find out the row height?
Any suggestions?
I added a quick sample to demonstrate the principal setup. When hitting one of the buttons I want only the DataGrid to scroll, not the ScrollViewer continaing the canvas.
<Window x:Class="ScrollTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<DockPanel>
<StackPanel DockPanel.Dock="Bottom" Orientation="Horizontal">
<Button Click="Button1_Click">Scroll to 1</Button>
<Button Click="Button100_Click">Scroll to 100</Button>
<Button Click="Button200_Click">Scroll to 200</Button>
</StackPanel>
<ScrollViewer>
<Canvas Width="5000" Height="5000">
<DataGrid Name="uxDataGrid" ItemsSource="{Binding TestItems}" Width="500" Height="500"></DataGrid>
</Canvas>
</ScrollViewer>
</DockPanel>
public class TestItem
{
public TestItem(int id)
{
Property1 = id.ToString();
Property2 = "B";
}
public string Property1 { get; set; }
public string Property2 { get; set; }
}
/// <summary>
/// Interaktionslogik für MainWindow.xaml
/// </summary>
public partial class Main开发者_运维技巧Window : Window
{
public IList<TestItem> TestItems { get; set; }
public MainWindow()
{
TestItems = new List<TestItem>();
for ( int i = 0; i < 300; i++ )
{
TestItems.Add(new TestItem(i));
}
InitializeComponent();
DataContext = this;
}
private void Button1_Click( object sender, RoutedEventArgs e )
{
uxDataGrid.ScrollIntoView( TestItems[0]);
}
private void Button100_Click( object sender, RoutedEventArgs e )
{
uxDataGrid.ScrollIntoView( TestItems[99] );
}
private void Button200_Click( object sender, RoutedEventArgs e )
{
uxDataGrid.ScrollIntoView( TestItems[199] );
}
}
Ok ...after some research I found the correct event: It's called RequestBringIntoViewEvent
. When intercepting that one, it is working as expected:
public partial class MainWindow : Window
{
public MainWindow()
{
...
uxDataGrid.AddHandler( RequestBringIntoViewEvent, new RoutedEventHandler( HandleRequestBringIntoViewEvent ) );
}
private static void HandleRequestBringIntoViewEvent( object sender, RoutedEventArgs e )
{
e.Handled = true;
}
...
}
精彩评论