检查绑定到 MVVM 应用程序中 ObservableCollection 的 ListBox 中的选定项目

Posted

技术标签:

【中文标题】检查绑定到 MVVM 应用程序中 ObservableCollection 的 ListBox 中的选定项目【英文标题】:Check for selected items in a ListBox bound to an ObservableCollection in a MVVM application 【发布时间】:2018-07-03 05:41:03 【问题描述】:

鉴于我的 MVVM 应用程序中的两个模型:

MyFolder 包含文件列表 (MyFiles):

public class MyFolder

    public string Path  get; set; 
    public int Id  get; set; 
    public List<MyFile> FilesList  get; set; 


public class MyFile

    public string Path  get; set; 
    public int Size  get; set; 

在我的 Viewmodel 中,我有一个带有文件夹的 ObservableCollection:

    public ObservableCollection<MyFolder> FoldersList  get; set; 

我正在查看一个 ListBox 中的文件夹,而在另一个 ListBox 中我显示了所选文件夹的文件列表(也在 ViewModel 中定义):

private MyFolder selectedFolder;

    public MyFolder SelectedFolder
    
        get  return selectedFolder; 
        set
        
            selectedFolder = value;
            OnPropertyChanged(nameof(SelectedFolder));
        
    

我需要的是能够选择列表框中显示的一些文件来对它们执行一些操作(比如说更改它们的扩展名)

<ListBox ItemsSource="Binding Path=FoldersList.FilesList"  SelectedItem="Binding Path=SelectedFolder, Mode=OneWayToSource">
    <ListBox.ItemTemplate>
        <DataTemplate>
            <StackPanel>
                <CheckBox IsChecked="Binding ????"/>
                <Label VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Content="Binding Path=Path">
             </StackPanel>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

我可以向 MyFiles 类添加一个属性,例如 bool Selected,然后将此属性绑定到 CheckBox。

但是,这是 MVVM 模式中的方法吗?

或者我应该怎么做?

非常感谢任何想法。 提前致谢

【问题讨论】:

差不多了。您的 ViewModel 类只是视图和模型之间的行为映射,您似乎没有这样的层。您在此处显示的类显然是模型类,但您应该在两者之间有一个 viewmodel 类。然后,该类将维护值,例如该项目是否在视图中被选中。 @LordWilmore 我很确定 OP 只发布了相关代码。他已经有一个视图模型来存储文件夹列表,所以我想我也有逻辑。 @DanieleSartori OP 询问正确的 MVVM 方法。 MyFile 和 MyFolder 类在我看来就像 Model 类。如果它们不是,它们实际上是 ViewModel 类,那么我们都是对的 ;) @LordWilmore:谢谢您的回复,是的,我确实有一个具有 FolderList 的虚拟机...但是您的意思是我仍然需要一个 FolderViewModel(我的模型的包装器),如下面的答案?我的虚拟机只有我填写的文件夹列表。 【参考方案1】:

您描述的方法对我来说似乎是合法的,但是请注意,您还必须在 MyFile 类中实现 INotifyPropertyChanged,否则您与复选框的绑定将不起作用。

<ListBox ItemsSource="Binding Path=FoldersList.FilesList"  SelectedItem="Binding Path=SelectedFolder, Mode=OneWayToSource">
   <ListBox.ItemTemplate>
       <DataTemplate>
          <StackPanel>
             <CheckBox IsChecked="Binding Checked"/>
             <Label VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Content="Binding Path=Path">
          </StackPanel>
       </DataTemplate>
   </ListBox.ItemTemplate>
</ListBox>



public class MyFile : INotifyPropertyChanged

    public void SetPropertyChanged(string propertyName)
    
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    
    public event PropertyChangedEventHandler PropertyChanged;
    public string Path  get; set; 
    public int Size  get; set; 
    private bool _checked = false;
    public bool Checked
    
        get return _checked;
        set
            
               _checked = value;
               SetPropertyChanged("Checked");
    

【讨论】:

谢谢.. 我已经实现了界面,但为了便于阅读问题而跳过了它 我就是这样做的。除非您不通过弄乱您的视图和视图模型来破坏 MVVM 模式,否则没关系。您选择的方法非常标准(通常我在像您这样的情况下也会这样做) @lebhero 你真的想要那个复选框吗?如果不是,您可以重新设置 ItemContainerTemplate 的样式以将 ListBoxItem 中的 IsSelected 绑定到您的模型 bool 属性。那么你不需要复选框,因为列表框提供了选择机制 @Milan 虽然这是真的,但我认为复选框更加“用户友好”。就应用程序的清晰度而言 感谢两位的建议。 CheckBox 确实是一个要求..【参考方案2】:

我建议使用 2 个视图模型

FolderViewModelFileViewModel,它们本质上都是模型类的包装器,但也可以具有与 UI 相关的功能。

因此,您的 fileViewModel 将有一个名为 IsSelected 或您需要的任何其他属性,您的 FolderViewModel 将拥有 FileViewModel 的集合。您可以通过使其更具可扩展性和更强大的 MVVM 从 fileViewModel 本身和那里触发您的属性更改

public class Folder

    //Model PROPERTIES
    IEnumerable<File> Files  get; set; 


public class File

    //Model PROPERTIES


public class FolderViewModel : INotifyPropertyChanged

    //View Model PROPERTIES
    IEnumerable<FileViewModel> Files  get; set; 


public class FileViewModel : INotifyPropertyChanged

    //View Model PROPERTIES
    public bool IsSelected  get; set; 

【讨论】:

感谢您的回答。这是否意味着我将“商业逻辑”排除在模型之外?对我来说,这就是我会做的,但这是一个很大的努力。但另一方面,像 isSelected 这样的属性不属于文件类 将模型视为存储库,模型中不应包含任何业务逻辑。模型可以在多个视图模型之间共享,考虑在两个视图上显示相同模型的情况,您选择一个而不选择另一个......但是在一个模型中使用 isSelected 会影响两个视图中的模型.....及时一针可节省九针 还考虑一种情况,您需要将重命名文件标记为突出显示,您会将这个逻辑放在哪里?文件模型??不!

以上是关于检查绑定到 MVVM 应用程序中 ObservableCollection 的 ListBox 中的选定项目的主要内容,如果未能解决你的问题,请参考以下文章

检查绑定到 MVVM 应用程序中 ObservableCollection 的 ListBox 中的选定项目

WPF MVVM:组合框 SelectedValue 绑定

MVVM 模块中闭包的目的是啥? [复制]

使用 MVVM 两种方式绑定到 AvalonEdit 文档文本

如何在 WPF / MVVM 中对绑定到相同实例的两个列表视图进行不同选择

MVVM:将带有 Observable 集合的命令绑定到 Listbox 并从文本框中获取值