簡體   English   中英

Scroll ListView To Top On ItemsSource Changed被意外調用

[英]Scroll ListView To Top On ItemsSource Changed Is Called Unexpectedly

我有一個wpf用戶控件項目設置類似(大部分) 使用Model-View-ViewModel設計模式WPF應用程序文章 基本上,我有一個帶有標簽控件的帶標題的內容控件。 第一個選項卡保存搜索結果,通過單擊搜索結果中的項目打開任何其他選項卡,以查看項目的更詳細視圖。

我的主要問題是,只要有人輸入搜索條件並運行搜索命令,我就會重復使用搜索結果選項卡。 重新填充搜索結果集合時滾動查看器不會滾動到頂部(如果用戶向下滾動列表)。

最初我以一種導致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.Selecting事件上分離您的行為,因此當您啟動或轉到搜索結果選項卡時,您將附加行為/屬性,當您轉到其他選項卡時,您可以分離/取消注冊該行為。

應該是這樣的:

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);
    }

}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM