将 WPF ListBox 滚动到视图模型中代码中设置的 SelectedItem [英] Scroll WPF ListBox to the SelectedItem set in code in a view model

查看:20
本文介绍了将 WPF ListBox 滚动到视图模型中代码中设置的 SelectedItem的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个带有列表框的 XAML 视图:

I have a XAML view with a list box:

<control:ListBoxScroll ItemSource="{Binding Path=FooCollection}"
                       SelectedItem="{Binding SelectedFoo, Mode=TwoWay}"
                       ScrollSelectedItem="{Binding SelectedFoo}">
    <!-- data templates, etc. -->
</control:ListBoxScroll>

在我看来,所选项目绑定到一个属性.当用户在列表框中选择一个项目时,我在视图模型中的 SelectedFoo 属性会更新.当我在视图模型中设置 SelectedFoo 属性时,会在列表框中选择正确的项目.

The selected item is bound to a property in my view. When the user selects an item in the list box my SelectedFoo property in the view model gets updated. When I set the SelectedFoo property in my view model then the correct item is selected in the list box.

问题是,如果在代码中设置的 SelectedFoo 当前不可见,我需要另外调用列表框中的 ScrollIntoView.由于我的 ListBox 在一个视图中,而我的逻辑在我的视图模型中......我找不到一种方便的方法来做到这一点.所以我扩展了 ListBoxScroll:

The problem is that if the SelectedFoo that is set in code is not currently visible I need to additionally call ScrollIntoView on the list box. Since my ListBox is inside a view and my logic is inside my view model ... I couldn't find a convenient way to do it. So I extended ListBoxScroll:

class ListBoxScroll : ListBox
{
    public static readonly DependencyProperty ScrollSelectedItemProperty = DependencyProperty.Register(
        "ScrollSelectedItem",
        typeof(object),
        typeof(ListBoxScroll),
        new FrameworkPropertyMetadata(
            null,
            FrameworkPropertyMetadataOptions.AffectsRender, 
            new PropertyChangedCallback(onScrollSelectedChanged)));
    public object ScrollSelectedItem
    {
        get { return (object)GetValue(ScrollSelectedItemProperty); }
        set { SetValue(ScrollSelectedItemProperty, value); }
    }

    private static void onScrollSelectedChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var listbox = d as ListBoxScroll;
        listbox.ScrollIntoView(e.NewValue);
    }
}

它基本上公开了一个新的依赖属性 ScrollSelectedItem,我将它绑定到我的视图模型上的 SelectedFoo 属性.然后我挂钩到依赖属性的属性更改回调并将新选择的项目滚动到视图中.

It basically exposes a new dependency property ScrollSelectedItem which I bind to the SelectedFoo property on my view model. I then hook into the property changed callback of the dependent property and scroll the newly selected item into view.

有没有其他人知道在由视图模型支持的 XAML 视图上调用用户控件上的函数的更简单方法?这有点跑题:

Does anyone else know of an easier way to call functions on user controls on a XAML view that is backed by a view model? It's a bit of a run around to:

  1. 创建依赖属性
  2. 向属性更改的回调添加回调
  3. 处理静态回调中的函数调用

将逻辑放在 ScrollSelectedItem { set { 方法中会很好,但依赖框架似乎偷偷摸摸并设法在没有实际调用它的情况下工作.

It would be nice to put the logic right in the ScrollSelectedItem { set { method but the dependency framework seems to sneak around and manages to work without actually calling it.

推荐答案

在查看答案后,出现了一个共同的主题:外部类监听 ListBox 的 SelectionChanged 事件.这让我意识到依赖属性方法是矫枉过正的,我可以让子类自己听:

After reviewing the answers a common theme came up: external classes listening to the SelectionChanged event of the ListBox. That made me realize that the dependant property approach was overkill and I could just have the sub-class listen to itself:

class ListBoxScroll : ListBox
{
    public ListBoxScroll() : base()
    {
        SelectionChanged += new SelectionChangedEventHandler(ListBoxScroll_SelectionChanged);
    }

    void ListBoxScroll_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        ScrollIntoView(SelectedItem);
    }
}

我觉得这是做我想做的最简单的解决方案.

I feel this is the simplest solution that does what I want.

值得一提的是 adcool2007 提出了 Behaviours.这里有几篇文章供感兴趣的人使用:

Honourable mention goes to adcool2007 for bringing up Behaviours. Here are a couple of articles for those interested:

http://blogs.msdn.com/b/johngossman/archive/2008/05/07/the-attached-behavior-pattern.aspx
http://www.codeproject.com/KB/WPF/AttachedBehaviors.aspx

我认为对于将添加到几个不同用户控件(例如单击行为、拖动行为、动画行为等)的通用行为,然后附加行为很有意义.我不想在这种特殊情况下使用它们的原因是行为的实现(调用 ScrollIntoView)不是一个通用操作,它不会发生在除 ListBox 之外的任何控件上.

I think for generic behaviours that will be added to several different user controls (e.g. click behaviours, drag behaviours, animation behaviours, etc.) then attached behaviours make a lot of sense. The reason I don't want to use them in this particular case is that the implementation of the behaviour (calling ScrollIntoView) isn't a generic action that can happen to any control other than a ListBox.

这篇关于将 WPF ListBox 滚动到视图模型中代码中设置的 SelectedItem的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆