用于WPF DataGrid的ScrollIntoView(MVVM)

And*_*ndy 16 c# wpf datagrid scroll mvvm

我正在使用MVVM模式,我在XAML中为DataGrid的SelectedItem创建了一个绑定.我以编程方式设置SelectedItem,但是当我这样做时,DataGrid不会滚动到选择.有没有办法在不完全打破MVVM模式的情况下实现这一目标?

我找到了以下解决方案但是当我尝试实现Behavior该类时出现错误,即使我已经安装了Blend SDK:http://www.codeproject.com/Tips/125583/ScrollIntoView-for-a havenGrid- when -使用- MVVM

Gje*_*ema 32

这应该工作.这个想法是你有这个附加属性,你将附加到DataGrid.在您附加它的xaml中,您将它绑定到您的属性上ViewModel.每当您想以编程方式为其分配值时SelectedItem,您还要为此属性设置一个值,附加属性绑定到该属性.

我已经将附加的属性类型设置为类型的任何SelectedItem类型,但老实说,只要将其设置为与之前不同的类型,类型是什么并不重要.此附加属性仅用作DataGrid以MVVM友好方式在视图控件(在本例中为a )上执行某些代码的方法.

那就是说,这是附加属性的代码:

namespace MyAttachedProperties
{
    public class SelectingItemAttachedProperty
    {
        public static readonly DependencyProperty SelectingItemProperty = DependencyProperty.RegisterAttached(
            "SelectingItem",
            typeof(MySelectionType),
            typeof(SelectingItemAttachedProperty),
            new PropertyMetadata(default(MySelectionType), OnSelectingItemChanged));

        public static MySelectionType GetSelectingItem(DependencyObject target)
        {
            return (MySelectionType)target.GetValue(SelectingItemProperty);
        }

        public static void SetSelectingItem(DependencyObject target, MySelectionType value)
        {
            target.SetValue(SelectingItemProperty, value);
        }

        static void OnSelectingItemChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
        {
            var grid = sender as DataGrid;
            if (grid == null || grid.SelectedItem == null)
                return;

            // Works with .Net 4.5
            grid.Dispatcher.InvokeAsync(() => 
            {
                grid.UpdateLayout();
                grid.ScrollIntoView(grid.SelectedItem, null);
            });

            // Works with .Net 4.0
            grid.Dispatcher.BeginInvoke((Action)(() =>
            {
                grid.UpdateLayout();
                grid.ScrollIntoView(grid.SelectedItem, null);
            }));
        }
    }
}
Run Code Online (Sandbox Code Playgroud)

这是xaml片段:

<Window ...
        xmlns:attachedProperties="clr-namespace:MyAttachedProperties">
    ...
        <DataGrid 
            attachedProperties:SelectingItemAttachedProperty.SelectingItem="{Binding MyViewModel.SelectingItem}">
            ...
        </DataGrid>
    </Grid>
Run Code Online (Sandbox Code Playgroud)


Edg*_*gar 18

我是MVVM的新手.我理解MVVM的想法,并尝试正确实现一切.我上面遇到了类似的问题,最后我在XAML中输入了1行,后面的代码中有1行.其余代码在VM中.我在XAML中做了以下事情

<ListBox DockPanel.Dock="Top"
    Name="Selection1List" 
    ItemsSource="{Binding SelectedList1ItemsSource}" 
    SelectedItem="{Binding SelectedList1Item}"
    SelectedIndex="{Binding SelectedList1SelectedIndex}"
    SelectionChanged="Selection1List_SelectionChanged">
Run Code Online (Sandbox Code Playgroud)

这在后面的代码中:

private void Selection1List_SelectionChanged(object sender, SelectionChangedEventArgs e) {
    Selection1List.ScrollIntoView(Selection1List.SelectedItem);
}
Run Code Online (Sandbox Code Playgroud)

这很好用.

我知道有些人甚至不想在窗口后面的代码中使用一行代码.但我认为这一行只是为了观点.它与数据或数据逻辑无关.所以我认为这不违反MVVM原则 - 而且更容易实现.

欢迎任何评论.

  • 很好的答案.我建议在使用`ScrollIntoView`之前对SelectedItem进行额外的空检查,因为代码会在从ItemsSource中删除项目时抛出NullReferenceException而没有任何选定的项目. (3认同)
  • 我确实建议像这样使用发送者:`if (sender is DataGrid dataGrid &amp;&amp; dataGrid.SelectedItem != null) dataGrid.ScrollIntoView(dataGrid.SelectedItem);` (2认同)