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