繁体   English   中英

如何在可导航的应用程序中支持 ListBox SelectedItems 与 MVVM 的绑定

[英]How to support ListBox SelectedItems binding with MVVM in a navigable application

我正在制作一个 WPF 应用程序,该应用程序可通过自定义“Next”和“Back”按钮和命令导航(即不使用NavigationWindow )。 在一个屏幕上,我有一个必须支持多项选择的ListBox (使用Extended模式)。 我对此屏幕有一个视图 model 并将所选项目存储为属性,因为它们需要维护。

但是,我知道ListBoxSelectedItems属性是只读的。 我一直在尝试使用这里的解决方案来解决这个问题,但我无法将它应用到我的实现中。 我发现我无法区分何时取消选择一个或多个元素以及何时在屏幕之间导航(在这两种情况下都会引发NotifyCollectionChangedAction.Remove ,因为从技术上讲,当导航离开屏幕时所有选定的项目都会被取消选择)。 我的导航命令位于一个单独的视图 model 中,该视图管理每个屏幕的视图模型,所以我不能在其中放置与视图 model 相关的任何实现和ListBox

我发现了其他几个不太优雅的解决方案,但这些似乎都没有在视图 model 和视图之间强制执行双向绑定。

任何帮助将不胜感激。 如果有助于理解我的问题,我可以提供一些源代码。

我正在制作一个可通过自定义“下一步”和“后退”按钮和命令(即不使用NavigationWindowNavigationWindow的 WPF 应用程序。 在一个屏幕上,我有一个必须支持多项选择的ListBox (使用Extended模式)。 我有这个屏幕的视图模型并将所选项目存储为属性,因为它们需要维护。

但是,我知道ListBoxSelectedItems属性是只读的。 我一直在尝试使用此解决方案来解决此问题,但我无法将其应用到我的实现中。 我发现我无法区分何时取消选择一个或多个元素以及何时在屏幕之间导航(在这两种情况下都会引发NotifyCollectionChangedAction.Remove ,因为从技术上讲,当导航离开屏幕时所有选定的项目都被取消选择)。 我的导航命令位于一个单独的视图模型中,该模型管理每个屏幕的视图模型,因此我无法在其中放置与带有ListBox的视图模型相关的任何实现。

我发现了其他几个不太优雅的解决方案,但这些解决方案似乎都没有强制执行视图模型和视图之间的双向绑定。

任何帮助将不胜感激。 如果有助于理解我的问题,我可以提供一些我的源代码。

我正在制作一个可通过自定义“下一步”和“后退”按钮和命令(即不使用NavigationWindowNavigationWindow的 WPF 应用程序。 在一个屏幕上,我有一个必须支持多项选择的ListBox (使用Extended模式)。 我有这个屏幕的视图模型并将所选项目存储为属性,因为它们需要维护。

但是,我知道ListBoxSelectedItems属性是只读的。 我一直在尝试使用此解决方案来解决此问题,但我无法将其应用到我的实现中。 我发现我无法区分何时取消选择一个或多个元素以及何时在屏幕之间导航(在这两种情况下都会引发NotifyCollectionChangedAction.Remove ,因为从技术上讲,当导航离开屏幕时所有选定的项目都被取消选择)。 我的导航命令位于一个单独的视图模型中,该模型管理每个屏幕的视图模型,因此我无法在其中放置与带有ListBox的视图模型相关的任何实现。

我发现了其他几个不太优雅的解决方案,但这些解决方案似乎都没有强制执行视图模型和视图之间的双向绑定。

任何帮助将不胜感激。 如果有助于理解我的问题,我可以提供一些我的源代码。

我正在制作一个可通过自定义“下一步”和“后退”按钮和命令(即不使用NavigationWindowNavigationWindow的 WPF 应用程序。 在一个屏幕上,我有一个必须支持多项选择的ListBox (使用Extended模式)。 我有这个屏幕的视图模型并将所选项目存储为属性,因为它们需要维护。

但是,我知道ListBoxSelectedItems属性是只读的。 我一直在尝试使用此解决方案来解决此问题,但我无法将其应用到我的实现中。 我发现我无法区分何时取消选择一个或多个元素以及何时在屏幕之间导航(在这两种情况下都会引发NotifyCollectionChangedAction.Remove ,因为从技术上讲,当导航离开屏幕时所有选定的项目都被取消选择)。 我的导航命令位于一个单独的视图模型中,该模型管理每个屏幕的视图模型,因此我无法在其中放置与带有ListBox的视图模型相关的任何实现。

我发现了其他几个不太优雅的解决方案,但这些解决方案似乎都没有强制执行视图模型和视图之间的双向绑定。

任何帮助将不胜感激。 如果有助于理解我的问题,我可以提供一些我的源代码。

我正在制作一个可通过自定义“下一步”和“后退”按钮和命令(即不使用NavigationWindowNavigationWindow的 WPF 应用程序。 在一个屏幕上,我有一个必须支持多项选择的ListBox (使用Extended模式)。 我有这个屏幕的视图模型并将所选项目存储为属性,因为它们需要维护。

但是,我知道ListBoxSelectedItems属性是只读的。 我一直在尝试使用此解决方案来解决此问题,但我无法将其应用到我的实现中。 我发现我无法区分何时取消选择一个或多个元素以及何时在屏幕之间导航(在这两种情况下都会引发NotifyCollectionChangedAction.Remove ,因为从技术上讲,当导航离开屏幕时所有选定的项目都被取消选择)。 我的导航命令位于一个单独的视图模型中,该模型管理每个屏幕的视图模型,因此我无法在其中放置与带有ListBox的视图模型相关的任何实现。

我发现了其他几个不太优雅的解决方案,但这些解决方案似乎都没有强制执行视图模型和视图之间的双向绑定。

任何帮助将不胜感激。 如果有助于理解我的问题,我可以提供一些我的源代码。

我正在制作一个可通过自定义“下一步”和“后退”按钮和命令(即不使用NavigationWindowNavigationWindow的 WPF 应用程序。 在一个屏幕上,我有一个必须支持多项选择的ListBox (使用Extended模式)。 我有这个屏幕的视图模型并将所选项目存储为属性,因为它们需要维护。

但是,我知道ListBoxSelectedItems属性是只读的。 我一直在尝试使用此解决方案来解决此问题,但我无法将其应用到我的实现中。 我发现我无法区分何时取消选择一个或多个元素以及何时在屏幕之间导航(在这两种情况下都会引发NotifyCollectionChangedAction.Remove ,因为从技术上讲,当导航离开屏幕时所有选定的项目都被取消选择)。 我的导航命令位于一个单独的视图模型中,该模型管理每个屏幕的视图模型,因此我无法在其中放置与带有ListBox的视图模型相关的任何实现。

我发现了其他几个不太优雅的解决方案,但这些解决方案似乎都没有强制执行视图模型和视图之间的双向绑定。

任何帮助将不胜感激。 如果有助于理解我的问题,我可以提供一些我的源代码。

我正在制作一个可通过自定义“下一步”和“后退”按钮和命令(即不使用NavigationWindowNavigationWindow的 WPF 应用程序。 在一个屏幕上,我有一个必须支持多项选择的ListBox (使用Extended模式)。 我有这个屏幕的视图模型并将所选项目存储为属性,因为它们需要维护。

但是,我知道ListBoxSelectedItems属性是只读的。 我一直在尝试使用此解决方案来解决此问题,但我无法将其应用到我的实现中。 我发现我无法区分何时取消选择一个或多个元素以及何时在屏幕之间导航(在这两种情况下都会引发NotifyCollectionChangedAction.Remove ,因为从技术上讲,当导航离开屏幕时所有选定的项目都被取消选择)。 我的导航命令位于一个单独的视图模型中,该模型管理每个屏幕的视图模型,因此我无法在其中放置与带有ListBox的视图模型相关的任何实现。

我发现了其他几个不太优雅的解决方案,但这些解决方案似乎都没有强制执行视图模型和视图之间的双向绑定。

任何帮助将不胜感激。 如果有助于理解我的问题,我可以提供一些我的源代码。

我正在制作一个可通过自定义“下一步”和“后退”按钮和命令(即不使用NavigationWindowNavigationWindow的 WPF 应用程序。 在一个屏幕上,我有一个必须支持多项选择的ListBox (使用Extended模式)。 我有这个屏幕的视图模型并将所选项目存储为属性,因为它们需要维护。

但是,我知道ListBoxSelectedItems属性是只读的。 我一直在尝试使用此解决方案来解决此问题,但我无法将其应用到我的实现中。 我发现我无法区分何时取消选择一个或多个元素以及何时在屏幕之间导航(在这两种情况下都会引发NotifyCollectionChangedAction.Remove ,因为从技术上讲,当导航离开屏幕时所有选定的项目都被取消选择)。 我的导航命令位于一个单独的视图模型中,该模型管理每个屏幕的视图模型,因此我无法在其中放置与带有ListBox的视图模型相关的任何实现。

我发现了其他几个不太优雅的解决方案,但这些解决方案似乎都没有强制执行视图模型和视图之间的双向绑定。

任何帮助将不胜感激。 如果有助于理解我的问题,我可以提供一些我的源代码。

我正在制作一个可通过自定义“下一步”和“后退”按钮和命令(即不使用NavigationWindowNavigationWindow的 WPF 应用程序。 在一个屏幕上,我有一个必须支持多项选择的ListBox (使用Extended模式)。 我有这个屏幕的视图模型并将所选项目存储为属性,因为它们需要维护。

但是,我知道ListBoxSelectedItems属性是只读的。 我一直在尝试使用此解决方案来解决此问题,但我无法将其应用到我的实现中。 我发现我无法区分何时取消选择一个或多个元素以及何时在屏幕之间导航(在这两种情况下都会引发NotifyCollectionChangedAction.Remove ,因为从技术上讲,当导航离开屏幕时所有选定的项目都被取消选择)。 我的导航命令位于一个单独的视图模型中,该模型管理每个屏幕的视图模型,因此我无法在其中放置与带有ListBox的视图模型相关的任何实现。

我发现了其他几个不太优雅的解决方案,但这些解决方案似乎都没有强制执行视图模型和视图之间的双向绑定。

任何帮助将不胜感激。 如果有助于理解我的问题,我可以提供一些我的源代码。

我正在制作一个可通过自定义“下一步”和“后退”按钮和命令(即不使用NavigationWindowNavigationWindow的 WPF 应用程序。 在一个屏幕上,我有一个必须支持多项选择的ListBox (使用Extended模式)。 我有这个屏幕的视图模型并将所选项目存储为属性,因为它们需要维护。

但是,我知道ListBoxSelectedItems属性是只读的。 我一直在尝试使用此解决方案来解决此问题,但我无法将其应用到我的实现中。 我发现我无法区分何时取消选择一个或多个元素以及何时在屏幕之间导航(在这两种情况下都会引发NotifyCollectionChangedAction.Remove ,因为从技术上讲,当导航离开屏幕时所有选定的项目都被取消选择)。 我的导航命令位于一个单独的视图模型中,该模型管理每个屏幕的视图模型,因此我无法在其中放置与带有ListBox的视图模型相关的任何实现。

我发现了其他几个不太优雅的解决方案,但这些解决方案似乎都没有强制执行视图模型和视图之间的双向绑定。

任何帮助将不胜感激。 如果有助于理解我的问题,我可以提供一些我的源代码。

我花了一段时间来实现绑定/使用 SelectedItems,因为我不是这方面的专家,所以如果有人觉得它有用,我想分享我的解决方案。 不要忘记为此解决方案从 Nuget 下载 Microsoft.Xaml.Behaviors.Wpf。

我受益于访问 WPF ListBox SelectedItems

看法:

Window x:Class="WpfAppSelectedItems.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:i="http://schemas.microsoft.com/xaml/behaviors" 
        xmlns:local="clr-namespace:WpfAppSelectedItems"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    
    <Grid>
        <ListBox Height="250" Width="300"
            ItemsSource="{Binding Items}" SelectionMode="Extended"
            >
            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem">
                    <Setter Property="IsSelected" Value="{Binding IsSelected}" />
                </Style>
            </ListBox.ItemContainerStyle>

            <ListBox.InputBindings>
                <KeyBinding Gesture="Ctrl+A" Command="{Binding SelectAllCommand}" />
            </ListBox.InputBindings>

            <i:Interaction.Triggers>
                <i:EventTrigger EventName="SelectionChanged" >
                    <i:CallMethodAction TargetObject="{Binding}" MethodName="ListBox_SelectionChanged"/>
                </i:EventTrigger>
            </i:Interaction.Triggers>
        </ListBox>

    </Grid>
</Window>

`

后面的代码:

namespace WpfAppSelectedItems
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            this.DataContext = new ViewModel(); //connecting window to VM
        }
    }
}

视图模型:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Linq;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Microsoft.Xaml.Behaviors;
using System.Windows;

namespace WpfAppSelectedItems
{
    internal class ViewModel: Presenter
    {
        //Creating ItemPresenter class. IsSelected binded to Style in the view
        public class ItemPresenter : Presenter
        {
            private readonly string _value;

            public ItemPresenter(string value)
            {
                _value = value;
            }

            public override string ToString()
            {
                return _value;
            }

            private bool _isSelected;
            public bool IsSelected
            {
                get { return _isSelected; }
                set
                {
                    _isSelected = value;
                    OnPropertyChanged();
                }
            }
        }

        //Placing items to the Items which is binded to the ListBox 
        public ObservableCollection<ItemPresenter> Items { get; } = new ObservableCollection<ItemPresenter>
        {
            new ItemPresenter("A"),
            new ItemPresenter("B"),
            new ItemPresenter("C"),
            new ItemPresenter("D")
        };

        //Do something when selection changed including detecting SelectedItems
        public void ListBox_SelectionChanged()
        {
            foreach (var item in Items)
            {
                if (item.IsSelected)
                    MessageBox.Show(fufuitem.ToString());
                    
            }
        }
    };

    //Notify View if a property changes
    public abstract class Presenter : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
        }
    }

}

如果您只想获取所选元素的名称,您可以执行以下操作:

看法:

<ListBox
    x:Name="Folders"
    Grid.Row="1"
    Grid.Column="0"
    ItemsSource="{Binding YourListWithStings}"
    SelectionMode="Single"
    SelectedItem="{Binding ToYourOutputVariable}"
    >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <TextBlock Text="{Binding}"/>
            </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

视图模型:

private string _ToYourOutputVariable
public string ToYourOutputVariable
{
    get {return _ToYourOutputVariable; }
    set 
       {
          _ToYourOutputVariable = value;
          NotifyOfPropertyChange(); 
          MessageBox.Show(_ToYourOutputVariable);
       }
}

messageBox 显示所选列表项的名称。 您可以在打开 MessageBox 的地方调用 function

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM