在我们当前的C#
MVVM
项目中,我们使用ListBox
显示项目。
还有一个可以在列表框下方展开的容器。
一切正常。容器展开后,ListBox
收缩,ScrollBar
出现。
但是,如果在列表框的底部选择了一个元素,并且容器已展开,则该项目会在ListBox
的末尾消失。
示例:
在容器扩展之前:
+--------------+
| Item 1 |
+--------------+
| Item 2 |
+--------------+
| Item 3 |
+--------------+
| Item 4 |
+--------------+
| SelectedItem |
+--------------+
| Item 6 |
+--------------+
| Item 7 |
+--------------+
+------------------+
| Container |
+------------------+
容器扩展后:
+--------------+---+
| Item 1 | S |
+--------------+ c |
| Item 2 | r |
+--------------+ o |
| Item 3 | l |
+--------------+ l |
| Item 4 | |
+--------------+---+
+------------------+
| |
| |
| Container |
| |
| |
+------------------+
我想实现的是保持SelectedItem
的可见性,而不必滚动到它。
像这样:
+--------------+---+
| Item 2 | S |
+--------------+ c |
| Item 3 | r |
+--------------+ o |
| Item 4 | l |
+--------------+ l |
| SelectedItem | |
+--------------+---+
+------------------+
| |
| |
| Container |
| |
| |
+------------------+
实现此目标的最佳方法是什么?
在SO或其他任何内容上我都找不到任何东西。
我已经看到可以以编程方式滚动:
我还看到有可能知道何时出现ListBoxItem
(here和there),但是由于我的物品已经加载,所以隐藏了,我不认为这会起作用。
我不想隐藏代码,我必须在需要此功能的每个视图中进行复制。我曾考虑过在ListBox
所附的行为中实施此操作,但我高度怀疑这是否是最佳解决方案。
我还考虑过编写自定义ListBox
控件,但是对于这么小的功能,我认为这太多了。
有人可以告诉我实现这种行为的最佳方法吗? 预先感谢。
答案 0 :(得分:1)
Behavior
是将此功能添加到控件的理想方法。选择更改或调整大小后,下面的代码将滚动列表框的SelectedItem进入视图。
public class perListBoxHelper : Behavior<ListBox>
{
protected override void OnAttached()
{
base.OnAttached();
AssociatedObject.SelectionChanged += AssociatedObject_SelectionChanged;
AssociatedObject.SizeChanged += AssociatedObject_SizeChanged;
}
protected override void OnDetaching()
{
AssociatedObject.SelectionChanged -= AssociatedObject_SelectionChanged;
AssociatedObject.SizeChanged -= AssociatedObject_SizeChanged;
base.OnDetaching();
}
private static void AssociatedObject_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
ScrollSelectionIntoView(sender as ListBox);
}
private static void AssociatedObject_SizeChanged(object sender, SizeChangedEventArgs e)
{
ScrollSelectionIntoView(sender as ListBox);
}
private static void ScrollSelectionIntoView(ListBox listBox)
{
if (listBox?.SelectedItem == null)
return;
Action action = () =>
{
listBox.UpdateLayout();
listBox.ScrollIntoView(listBox.SelectedItem);
};
listBox.Dispatcher.BeginInvoke(action, DispatcherPriority.ContextIdle);
}
}
用法
<ListBox ... >
<i:Interaction.Behaviors>
<vhelp:perListBoxHelper />
</i:Interaction.Behaviors>
</ListBox>
关于我最近的blog post的行为的更多讨论。