当这个ItemsControl的Items丢失元素时,ScrollViewer似乎有一个默认行为,使其滚动到ItemsControl。
举个例子:
<ScrollViewer>
<ItemsControl>
<TextBlock Text="Something"/>
<TextBlock Text="Something"/>
<TextBlock Text="Something"/>
<TextBlock Text="Something"/>
<TextBlock Text="Something"/>
<TextBlock Text="Something"/>
<TextBlock Text="Something"/>
<TextBlock Text="Something"/>
<TextBlock Text="Something"/>
<TextBlock Text="Something"/>
<ItemsControl>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
<Button Click="ButtonBase_OnClick">
<TextBlock Text="Some item"/>
</Button>
</ItemsControl>
</ItemsControl>
</ScrollViewer>
使用ButtonBase_OnClick定义如下:
private void ButtonBase_OnClick(object sender, RoutedEventArgs e) {
((sender as Button).Parent as ItemsControl).Items.Remove(sender);
}
在采取任何行动之前,它看起来像这样:
但是,如果我点击一个按钮(它将从ItemsControl中删除):
如果我添加项目而不是删除项目,则不会发生。我该如何防止这种行为?
修改
如果我添加此代码,则不会发生:
Loaded += (sender, args) => {
new Thread(() => {
Thread.Sleep(1500);
Dispatcher.Invoke(new Action(() => {
MyItemsControl.Items.Remove(MyItemsControl.Items[1]);
}));
}).Start();
};
但是,如果我添加:
(MyItemsControl.Items[1] as FrameworkElement).Focus();
在我删除之前,行为就会发生。
所以当任何项目被移除时都不会,但只有当项目具有焦点时才会被删除。因此,解决此问题的方法是在删除之前从项目中删除Focus。
有没有更方便的方法来阻止它发生?
编辑n°2
我没有说明我正在使用框架.Net v3.5。在@ Joseph的评论之后我用4.5.1尝试了它,事实上这在4.5.1中没有发生。
答案 0 :(得分:1)
问题确实很棘手,我不确定以下是否是确切的解决方案,但肯定是一种解决方法。
我做的唯一更改是在点击事件中删除项目后添加一行(即将焦点从按钮或项目控件设置为父级或窗口)。
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
((sender as Button).Parent as ItemsControl).Items.Remove(sender);
this.Focus();
}
我在上面进行了一个简单的测试并且已经实现了所需的行为,如果这不是您想要的,请告诉我吗?
答案 1 :(得分:1)
似乎(显然)会触发一些额外的滚动事件,我试图检查ScrollView
收到的所有事件,但我仍然没有找到适当的解决这个bug的工作!
既然你需要使用.net 3.5这里有一个Old School hack,我希望它会有所帮助
首先添加ScrollChanged
事件处理程序并命名您的ScrollViewer
<ScrollViewer x:Name="sc" ScrollChanged="Sc_OnScrollChanged">
<ItemsControl >
<TextBlock Text="Something"/>
<TextBlock Text="Something"/>
第二次将您的代码隐藏更改为以下
private int _cpt;
private double _save;
private void ButtonBase_OnClick(object sender, RoutedEventArgs e)
{
((sender as Button).Parent as ItemsControl).Items.Remove(sender);
_cpt = 0;
}
private void Sc_OnScrollChanged(object sender, ScrollChangedEventArgs e)
{
if (_cpt < 3)
{
if (_cpt == 0)
{
_save = sc.VerticalOffset;
}
//sc.ScrollToTop();
sc.ScrollToVerticalOffset(_save);
_cpt++;
}
}
它有点像马铃薯解决方案,但它就像一个魅力。