首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >问答首页 >WPF ListView从视图模型滚动

WPF ListView从视图模型滚动
EN

Stack Overflow用户
提问于 2014-12-02 05:36:38
回答 3查看 1.1K关注 0票数 0

我在视图模型中有一个名为(Users)的可观察集合,它与视图中的ListViewControl (lstUsers)绑定在一起,我需要的是滚动到列表视图中当前登录的用户。我在大多数使用scroll from code的例子中都看到了如下内容:

代码语言:javascript
运行
复制
lstUsers.ScrollIntoView(lstUsers[5]);

但我需要的是从视图模型中处理它。

请多多指教!

EN

回答 3

Stack Overflow用户

发布于 2014-12-02 07:00:41

要做到这一点,一种方法是使用像ICollectionView这样的东西,它具有当前项。然后,您可以将IsSynchronizedWithCurrentItem设置为true,以将视图模型中的当前项链接到ListView中的选定项。

最后,在视图后面的代码中处理事件SelectionChanged,以更改滚动位置,使其始终显示所选项目。

对我来说,这种方法的好处是视图模型不知道视图的任何内容,这是MVVM的目标之一。视图背后的代码是任何只涉及视图的代码的完美位置。

代码语言:javascript
运行
复制
<Grid>
    <Grid.RowDefinitions>
        <RowDefinition/>
        <RowDefinition Height="Auto"/>
    </Grid.RowDefinitions>
    <ListView x:Name="View"
              SelectionChanged="Selector_OnSelectionChanged" IsSynchronizedWithCurrentItem="True" ItemsSource="{Binding Items}"/>
    <Button Grid.Row="1" Command="{Binding ChangeSelectionCommand}">Set</Button>       
</Grid> 


public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();
        DataContext = new ViewModel();
    }

    private void Selector_OnSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        View.ScrollIntoView(View.SelectedItem);
    }
}

public class ViewModel
{
    private readonly CollectionViewSource _source = new CollectionViewSource();

    public ICollectionView Items
    {
        get { return _source.View; }
    }

    public ICommand ChangeSelectionCommand { get; set; }

    public ViewModel()
    {
        SetUp();
        ChangeSelectionCommand = new Command(ChangeSelection);
    }

    private void SetUp()
    {
        var list = new List<string>();
        for (int i = 0; i < 100; i++)
        {
            list.Add(i.ToString(CultureInfo.InvariantCulture));
        }
        _source.Source = list;
    }

    private void ChangeSelection()
    {
        var random = new Random(DateTime.Now.Millisecond);

        var n = random.Next(100);

        Items.MoveCurrentToPosition(n);
    }
}

public class Command : ICommand
{
    private readonly Action _action;

    public bool CanExecute(object parameter)
    {
        return true;
    }

    public void Execute(object parameter)
    {
        _action();
    }

    public event EventHandler CanExecuteChanged;

    public Command(Action action)
    {
        _action = action;
    }
}
票数 1
EN

Stack Overflow用户

发布于 2018-11-15 20:53:03

让我与您分享我的解决方案

  1. 使用依赖属性TargetListItem创建您自己的ListView后代

公共类ScrollableListView : ListView {/设置此属性使ListView滚动到它/公共对象TargetListItem { get { return ( object )GetValue( TargetListItemProperty );} set { SetValue(TargetListItemProperty,value);}}公共静态只读DependencyProperty TargetListItemProperty= DependencyProperty.Register( DependencyProperty.Register(TargetListItem),typeof(object),typeof(ScrollableListView),new PropertyMetadata(null,TargetListItemPropertyChangedCallback));静态空值d,DependencyPropertyChangedEventArgs e) { var TargetListItemPropertyChangedCallback(DependencyObject = (ScrollableListView)d;owner.ScrollToItem(e.NewValue);} public void ScrollToItem(对象值){ if (value != null && Items != null && Items.Contains(值)){ScrollIntoView(值);}

  • 在ViewModel中创建属性

object currentListItem;公共对象名称urrentListItem{ get =>СurrentListItem;{ if (сurrentListItem != value) {сurrentListItem = value;OnPropertyChanged(nameof(СurrentListItem);}

  • 绑定它

<controls:ScrollableListView ... TargetListItem="{Binding CurrentListItem}"/>

现在,您可以在需要时在ViewModel中设置CurrentListItem。并且相应的可视元素将立即在ListView中变为可见。

另外,也许你可以在ListView上使用附加属性,而不是创建ScrollableListView。但我不确定。

票数 0
EN

Stack Overflow用户

发布于 2014-12-02 06:31:19

是的,在MVVM中总会有你需要控制的时候。有多种方法可以做到这一点,但这里有一种简单的方法,不用从WPF中的控件派生或处理路由命令或其他类似的玩意儿。

总而言之:

  • 在视图模型上创建附加属性。
  • 在XAML中设置attached属性以将列表框传递回视图模型。
  • 按需调用.ScrollIntoView。

请注意,这是一个粗略的示例,请确保在显示窗口之前设置了您的DataContext。

代码/视图模型:

代码语言:javascript
运行
复制
public class ViewModel
{
    private ListBox _listBox;

    private void ReceiveListBox(ListBox listBox)
    {
        _listBox = listBox;
    }

    public static readonly DependencyProperty ListBoxHookProperty = DependencyProperty.RegisterAttached(
        "ListBoxHook", typeof (ListBox), typeof (ViewModel), new PropertyMetadata(default(ListBox), ListBoxHookPropertyChangedCallback));

    private static void ListBoxHookPropertyChangedCallback(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs dependencyPropertyChangedEventArgs)
    {
        var listBox = (ListBox) dependencyObject;
        var viewModel = (ViewModel) listBox.DataContext;
        viewModel.ReceiveListBox(listBox);
    }

    public static void SetListBoxHook(DependencyObject element, ListBox value)
    {
        element.SetValue(ListBoxHookProperty, value);
    }

    public static ListBox GetListBoxHook(DependencyObject element)
    {
        return (ListBox) element.GetValue(ListBoxHookProperty);
    }
}

好的,这将让我们将ListBox传递回视图;您可以随心所欲地处理它。

现在,只需在XAML中设置属性:

代码语言:javascript
运行
复制
<ListBox wpfApplication1:ViewModel.ListBoxHook="{Binding RelativeSource={RelativeSource Self}}" />

可以开始了!

票数 -1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27237786

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档