代码之家  ›  专栏  ›  技术社区  ›  Maël Pedretti

wpf:如何在调整大小后保持列表框selecteditem可见?

  •  0
  • Maël Pedretti  · 技术社区  · 7 年前

    在我们当前 C# MVVM 我们使用的项目 ListBox 显示项目。

    列表框下方还有另一个可展开的容器。

    一切正常。当容器膨胀时, 列表框 合同和 ScrollBar 出现。

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

    例子:

    容器膨胀前:

    +--------------+
    | 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 进入视野( here 和 there )但由于我的物品已经加载,所以我认为这不起作用。

    我不想让代码隐藏在后面,我必须在我需要此功能的每个视图中进行复制。我已经考虑过在附加到 列表框 但我非常怀疑这是最好的解决办法。

    我也想过写一个风俗 列表框 控制,但我认为这对于如此小的功能来说太多了。

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

    1 回复  |  直到 7 年前
        1
  •  1
  •   Peregrine    7 年前

    一 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 .

    推荐文章