C# WPF:调整大小后如何保持ListBox SelectedItem可见?

C# WPF:调整大小后如何保持ListBox SelectedItem可见?,c#,wpf,xaml,scroll,listbox,C#,Wpf,Xaml,Scroll,Listbox,在我们当前的C#MVVM项目中,我们使用列表框来显示项目 还有一个容器可以在列表框下面展开 一切正常。当容器展开时,列表框收缩并出现滚动条 但是,如果在列表框底部选择了一个元素并展开了容器,则该项将在列表框的末尾消失 例如: 容器扩展前: +--------------+ | Item 1 | +--------------+ | Item 2 | +--------------+ | Item 3 | +--------------+ | Item 4

在我们当前的
C#
MVVM
项目中,我们使用
列表框来显示项目

还有一个容器可以在列表框下面展开

一切正常。当容器展开时,
列表框
收缩并出现
滚动条

但是,如果在列表框底部选择了一个元素并展开了容器,则该项将在
列表框的末尾消失

例如:

容器扩展前:

+--------------+
| 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        |
|                  |
|                  |
+------------------+
容器扩展后:

+--------------+
| 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        |
|                  |
|                  |
+------------------+
实现这一目标的最佳方式是什么

我在这里找不到任何关于这件事的东西

我已经看到可以通过编程方式滚动:

我还看到,可以知道何时可以看到
ListBoxItem
,但由于我的项目已经加载,然后隐藏,我认为这不起作用

我不想在需要这种功能的每个视图中都复制代码。我曾想过在
列表框
的行为中实现这一点,但我非常怀疑这是最好的解决方案

我还考虑过编写一个自定义的
列表框
控件,但我认为这对于这样一个小功能来说太多了

有人能告诉我实现这种行为的最佳方法吗? 提前感谢。

A是将此功能添加到控件的理想方法。更改选择或调整大小后,下面的代码会将列表框的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);
    }
}
公共类perListBoxHelper:行为
{
受保护的覆盖无效附加()
{
base.onatached();
AssociatedObject.SelectionChanged+=AssociatedObject\u SelectionChanged;
AssociatedObject.SizeChanged+=AssociatedObject\u SizeChanged;
}
附加时受保护的覆盖无效()
{
AssociatedObject.SelectionChanged-=AssociatedObject\u SelectionChanged;
AssociatedObject.SizeChanged-=AssociatedObject\u SizeChanged;
base.OnDetaching();
}
私有静态无效关联对象\u SelectionChanged(对象发送者,SelectionChangedEventArgs e)
{
滚动选择查看(发件人为列表框);
}
私有静态无效关联对象\u SizeChanged(对象发送方,SizeChangedEventArgs e)
{
滚动选择查看(发件人为列表框);
}
私有静态无效滚动选择视图(列表框列表框)
{ 
如果(列表框?.SelectedItem==null)
回来
动作动作=()=>
{
UpdateLayout();
listBox.ScrollIntoView(listBox.SelectedItem);
};
listBox.Dispatcher.BeginInvoke(操作,DispatcherPriority.ContextIdle);
}
}
用法



更多关于我最近的行为的讨论。

非常感谢!这正是我需要的!我只是不明白为什么你也听selectionChanged,因为我们允许多重选择,所以不得不删除这个部分。但再一次,谢谢你。我会好好看看你的博客!SelectionChanged是此行为最初设计用来处理的-当您从代码隐藏或通过绑定选择项目时,它将滚动到视图中。哦,我明白了,谢谢!我不需要这个部分,因为它不会发生在我的情况下,但它可能会有用的一天。再次感谢你,也许最好是做出两种截然不同的行为——每一个事件一个。然后,您可以为每个特定的Listbox实例添加适当的内容。