加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 百科 > 正文

c# – Scroll ListView To Top On ItemsSource Changed被意外调

发布时间:2020-12-15 21:54:00 所属栏目:百科 来源:网络整理
导读:我有一个wpf用户控件项目设置类似(大部分)到 WPF Apps With The Model-View-ViewModel Design Pattern article.基本上,我有一个带有标签控件的带标题的内容控件.第一个选项卡保存搜索结果,通过单击搜索结果中的项目打开任何其他选项卡,以查看项目的更详细视
我有一个wpf用户控件项目设置类似(大部分)到 WPF Apps With The Model-View-ViewModel Design Pattern article.基本上,我有一个带有标签控件的带标题的内容控件.第一个选项卡保存搜索结果,通过单击搜索结果中的项目打开任何其他选项卡,以查看项目的更详细视图.

我的主要问题是,只要有人输入搜索条件并运行搜索命令,我就会重复使用搜索结果选项卡.重新填充搜索结果集合时滚动查看器不会滚动到顶部(如果用户向下滚动列表).

最初我以一种导致CollectionChanged事件触发的方式重新填充搜索结果项集合.然后我查看使用附加属性允许滚动到顶部,看起来好像更换整个集合是要走的路(因为ItemsControl没有实现ICollectionNotifyChanged接口).

所以我做了改变,一切都很顺利.运行新搜索替换了搜索结果项集合,该集合触发了附加属性并将列表视图滚动回顶部.但是,我现在遇到一个问题,每当我移动到另一个选项卡查看项目的详细视图时,它会触发附加属性并将第一个选项卡上的搜索结果滚动到顶部.我不知道如何解决这种情况.

public static class ScrollToTopBehavior
{
    public static readonly DependencyProperty ScrollToTopProperty =
        DependencyProperty.RegisterAttached
            (
                "ScrollToTop",typeof (bool),typeof (ScrollToTopBehavior),new UIPropertyMetadata(false,OnScrollToTopPropertyChanged)
            );

    public static bool GetScrollToTop(DependencyObject obj)
    {
        return (bool) obj.GetValue(ScrollToTopProperty);
    }

    public static void SetScrollToTop(DependencyObject obj,bool value)
    {
        obj.SetValue(ScrollToTopProperty,value);
    }

    private static void OnScrollToTopPropertyChanged(DependencyObject dpo,DependencyPropertyChangedEventArgs e)
    {
        var itemsControl = dpo as ItemsControl;
        if (itemsControl == null) return;

        DependencyPropertyDescriptor dependencyPropertyDescriptor =
            DependencyPropertyDescriptor.FromProperty(ItemsControl.ItemsSourceProperty,typeof (ItemsControl));
        if (dependencyPropertyDescriptor == null) return;
        if ((bool) e.NewValue)
        {
            dependencyPropertyDescriptor.AddValueChanged(itemsControl,ItemsSourceChanged);
        }
        else
        {
            dependencyPropertyDescriptor.RemoveValueChanged(itemsControl,ItemsSourceChanged);
        }
    }

    private static void ItemsSourceChanged(object sender,EventArgs e)
    {
        var itemsControl = sender as ItemsControl;
        EventHandler eventHandler = null;
        eventHandler = delegate
            {
                if (itemsControl != null &&
                    itemsControl.ItemContainerGenerator.Status == GeneratorStatus.ContainersGenerated)
                {
                    var scrollViewer = VisualTreeHelpers.FindChild<ScrollViewer>(itemsControl);
                    scrollViewer.ScrollToTop();
                    itemsControl.ItemContainerGenerator.StatusChanged -= eventHandler;
                }
            };
        if (itemsControl != null) itemsControl.ItemContainerGenerator.StatusChanged += eventHandler;
    }
}

我已将此属性附加到搜索结果用户控件,如下所示:

<ListView ...some properties left out for brevity...
              DataContext="{StaticResource SearchResultsViewSource}"
              IsSynchronizedWithCurrentItem="True"
              ItemsSource="{Binding}"
              SelectionMode="Single"
              behaviours:ScrollToTopBehavior.ScrollToTop="True">
...etc...

搜索结果控件位于另一个使用带标题内容控件的用户控件内(如果需要,我将提供详细信息).

解决方法

这是一个黑客,并没有解决你的真正问题,但它将解决症状.
你可以在tabControl上分离你的行为.选择事件,
因此,当您启动或转到搜索结果选项卡时,您会附加行为/属性,当您转到其他选项卡时,您可以分离/取消注册该行为.

应该是这样的:

yourTab.SelecnionChanged+= new TabControlCancelEventHandler(tabControl_Selecting);

void tabControl_SelecnionChange(DependencyObject sender,DependencyPropertyChangedEventArgs e)
{
    var current = (sender as TabControl).SelectedValue;

    //check if current is search tab then
    {
      ScrollToTopBehavior.SetScrollToTop(yourList,true);
    }
    else
    {
      ScrollToTopBehavior.SetScrollToTop(yourList,false);
    }

}

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读