【问题标题】:Displaying selected item in listbox upon changing selected index || scrolling ListBox更改所选索引时在列表框中显示所选项目||滚动列表框
【发布时间】:2017-06-20 13:57:14
【问题描述】:

我有一个列表框,其中显示了书籍。 SelectedIndexCurrentindex 绑定到 Viewmodel 中的属性。 ListBox 下方是两个按钮,即从 Viewmodel 中的 SelectedIndex 属性中添加(下一个)或减去(最后一个)一个按钮。

<DockPanel LastChildFill="False">
    <ListBox DockPanel.Dock="Top"
             ItemsSource="{Binding Books, Mode=OneWay}"
             SelectedItem="{Binding CurrentBook, Mode=TwoWay}" 
             SelectedIndex="{Binding SelectedIndex}"
             />
    <StackPanel Orientation="Horizontal" DockPanel.Dock="Bottom">
        <Button Content="Last" Command="{Binding ChangeBook}" CommandParameter="last"/>
        <Button Content="Next" Command="{Binding ChangeBook}" CommandParameter="next"/>
    </StackPanel>
</DockPanel>

点击NextLast 按钮会更改列表框的索引。没有发生的是,当 Index 离开用户的可见区域时,ListBox 不会向下滚动,从而使所选索引保持可见。

我想知道如何实现,除非用户滚动离开,否则 SelectedItem 在 ListBox 中始终可见。
当然,我想这样做,而不是在这样做时破坏 MVVM 模式。

【问题讨论】:

    标签: c# wpf xaml mvvm listbox


    【解决方案1】:

    这是在不违反 MVVM 的情况下执行此操作的方法。

    <ListBox DockPanel.Dock="Top"
             ItemsSource="{Binding Books, Mode=OneWay}"
             SelectedItem="{Binding CurrentBook, Mode=TwoWay}" 
             SelectedIndex="{Binding SelectedIndex}"
             SelectionChanged="ListBox_SelectionChanged"
             />
    

    后面的代码:

    private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var lb = (ListBox)sender;
    
        lb.ScrollIntoView(lb.SelectedItem);
    }
    

    这是一种更体面的方式。对于这种事情使用背后的代码并没有错误,但是如果像这样的某些行为将在不同的视图中多次使用,则使用附加属性比复制和粘贴更方便事件处理程序。此外,它现在可以在DataTemplate 等上下文中使用,其中可能没有代码。

    前面还有一些代码,但您可以轻松地将附加属性添加到项目中的任何ListBox

    public static class ListBoxExtensions
    {
        #region ListBoxExtensions.KeepSelectedItemVisible Attached Property
        public static bool GetKeepSelectedItemVisible(ListBox lb)
        {
            return (bool)lb.GetValue(KeepSelectedItemVisibleProperty);
        }
    
        public static void SetKeepSelectedItemVisible(ListBox lb, bool value)
        {
            lb.SetValue(KeepSelectedItemVisibleProperty, value);
        }
    
        public static readonly DependencyProperty KeepSelectedItemVisibleProperty =
            DependencyProperty.RegisterAttached("KeepSelectedItemVisible", typeof(bool), typeof(ListBoxExtensions),
                new PropertyMetadata(false, KeepSelectedItemVisible_PropertyChanged));
    
        private static void KeepSelectedItemVisible_PropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            var lb = (ListBox)d;
    
            if ((bool)e.NewValue)
            {
                lb.SelectionChanged += ListBox_SelectionChanged;
                ScrollSelectedItemIntoView(lb);
            }
            else
            {
                lb.SelectionChanged -= ListBox_SelectionChanged;
            }
        }
    
        private static void ScrollSelectedItemIntoView(ListBox lb)
        {
            lb.ScrollIntoView(lb.SelectedItem);
        }
    
        private static void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            ScrollSelectedItemIntoView((ListBox)sender);
        }
        #endregion ListBoxExtensions.KeepSelectedItemVisible Attached Property
    }
    

    XAML:

    <ListBox DockPanel.Dock="Top"
             ItemsSource="{Binding Books, Mode=OneWay}"
             SelectedItem="{Binding CurrentBook, Mode=TwoWay}" 
             SelectedIndex="{Binding SelectedIndex}"
             local:ListBoxExtensions.KeepSelectedItemVisible="True"
             />
    

    【讨论】:

    • 感谢您的快速回复,明天会查看它^^
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-22
    • 2013-01-23
    • 1970-01-01
    • 1970-01-01
    • 2023-03-10
    相关资源
    最近更新 更多