[英]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.