【问题标题】:How to handle ItemClick For Nested ListView In MVVM Pattern?如何处理 MVVM 模式中嵌套 ListView 的 ItemClick?
【发布时间】:2018-12-27 22:12:08
【问题描述】:

Xaml 代码:

<Page
    x:Class="DemoTestApp.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:local="using:DemoTestApp"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
    xmlns:vm="using:ViewModels"
    >

    <Page.DataContext>
       <vm:TestViewModel/>
   </Page.DataContext>

   <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
       <ListView Name="HeaderList" ItemsSource="{Binding Items}">
           <ListView.ItemTemplate>
               <DataTemplate>
                    <Grid>
                        <Border Background="Bisque">
                            <TextBlock Text="{Binding Name}"/>
                        </Border>
                        <ListView Name="SubItemsList">
                            <x:String>SubItem 1</x:String>
                            <x:String>SubItem 2</x:String>
                            <x:String>SubItem 3</x:String>
                        </ListView>
                    </Grid>
                </DataTemplate>
            </ListView.ItemTemplate>
        </ListView>
    </Grid>
</Page>

ViewModel 代码:

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace ViewModels
{


class TestViewModel
{
    public class Item
    {
        public string Test { get; set; }
    }

    public ObservableCollection<Item> Items { get; set; }

    public TestViewModel()
    {
        Items = new ObservableCollection<Item>();

        Items.Add(new Item { Test = "Item 1" });
        Items.Add(new Item { Test = "Item 2" });
        Items.Add(new Item { Test = "Item 3" });
        Items.Add(new Item { Test = "Item 4" });
        Items.Add(new Item { Test = "Item 5" });
        Items.Add(new Item { Test = "Item 7" });
        Items.Add(new Item { Test = "Item 8" });
        Items.Add(new Item { Test = "Item 9" });
            Items.Add(new Item { Test = "Item 10" });
        Items.Add(new Item { Test = "Item 11" });
        }
    }
    }

这是演示我的问题的演示代码。

当我单击 SubItemsList 上的任何项目时,我希望将事件绑定到视图模型中的命令,我该如何实现?

感谢阅读。

我已经查看了 stackoverflow 中的两个资源,但没有一个有用。

仅供参考,我是 UWP 的新手,对 MVVM 更是如此。

【问题讨论】:

    标签: c# mvvm uwp mvvm-light listviewitem


    【解决方案1】:

    对于嵌套在 MVVM 模式中的ListView ItemClick,您可以使用Xaml Behaviors SDK 添加ItemClick 事件,如下所示。

    <ListView Name="HeaderList"  ItemsSource="{Binding Items}" >
        <ListView.ItemTemplate>
            <DataTemplate>
                <Grid>
                    <Border Background="Bisque">
                        <TextBlock Text="{Binding Test}"/>
                    </Border>
    
                    <ListView Name="SubItemsList" ItemsSource="{Binding SubItems}" 
                               IsItemClickEnabled="True" 
                               SelectedItem="{Binding SelectItme,Mode=TwoWay}" >
                        <ListView.ItemTemplate>
                            <DataTemplate>
                                <StackPanel Orientation="Vertical">
                                    <TextBlock Text="{Binding }"/>
                                </StackPanel>
                            </DataTemplate>
                        </ListView.ItemTemplate>
    
                        <i:Interaction.Behaviors >
                            <ic:EventTriggerBehavior  EventName="ItemClick">
                                <ic:InvokeCommandAction  Command="{Binding ItemCommand}" 
                                                         CommandParameter="{Binding}" />
                            </ic:EventTriggerBehavior>
                        </i:Interaction.Behaviors>
                    </ListView>
                </Grid>
            </DataTemplate>
        </ListView.ItemTemplate>
    </ListView>
    

    您需要添加SelectedItem="{Binding SelectItme,Mode=TwoWay}" 用于标识您选择了哪个项目。

    视图模型

    class TestViewModel
    {
        public class Item : INotifyPropertyChanged
        {
            public event PropertyChangedEventHandler PropertyChanged;
            public void OnPropertyChanged([CallerMemberName] string propertyName = null)
            {
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
            public string Test { get; set; }
            public ObservableCollection<string> SubItems { get; set; }
    
            private string _selectItme;
    
            public string SelectItme
            {
                get
                {
                    return _selectItme;
                }
                set
                {
                    _selectItme = value;
                    OnPropertyChanged();
                }
            }
            public Item()
            {
                SubItems = new ObservableCollection<string>() { "zhuzhu", "heheh", "liuliu", "momo" };
            }
    
            public ICommand ItemCommand
            {
                get
                {
                    return new CommadEventHandler<object>((item) => ItemClick(item));
                }
            }
            private void ItemClick(object item)
            {
                System.Diagnostics.Debug.WriteLine("--------------------");
            }
        }
    
        public ObservableCollection<Item> Items { get; set; }
    
        public TestViewModel()
        {
            Items = new ObservableCollection<Item>();
    
            Items.Add(new Item { Test = "Item 1" });
            Items.Add(new Item { Test = "Item 2" });
            Items.Add(new Item { Test = "Item 3" });
            Items.Add(new Item { Test = "Item 4" });
            Items.Add(new Item { Test = "Item 5" });
            Items.Add(new Item { Test = "Item 7" });
            Items.Add(new Item { Test = "Item 8" });
            Items.Add(new Item { Test = "Item 9" });
            Items.Add(new Item { Test = "Item 10" });
            Items.Add(new Item { Test = "Item 11" });
        }
    
    }
    
    class CommadEventHandler<T> : ICommand
    {
        public event EventHandler CanExecuteChanged;
    
        public Action<T> action;
        public bool CanExecute(object parameter)
        {
            return true;
        }
    
        public void Execute(object parameter)
        {
            this.action((T)parameter);
        }
        public CommadEventHandler(Action<T> action)
        {
            this.action = action;
    
        }
    }
    

    【讨论】:

    • 不客气,这是code sample,你可以参考。
    • 如果我不想将处理程序保留在 Item 中,而不是将其处理程序放在 ViewModel 中怎么办?那可能吗?在我的项目中,我一直在做你在那里展示的事情,:D 但是在我的项目中,项目是模型的一部分......所以我对在模型中放置一个事件处理程序(命令)感到很奇怪......请告诉我是否你明白我在说什么。再次感谢。 :)
    • 是的,我知道你的意思,但是subListView的DataContext是Item而不是TestViewModel,所以最好在Item类中做命令。
    • 为什么“更好”?你的意思是它更容易/更方便? :D 我们想成为 MVVM 纯粹主义者。不确定这是否是纯粹的方式。
    • 如果你想在TestViewModel绑定命令,你可以尝试使用x:Bind,更多你可以参考this
    猜你喜欢
    • 2017-03-11
    • 2017-10-11
    • 1970-01-01
    • 2018-12-14
    • 2013-10-28
    • 2011-02-04
    • 2020-12-29
    • 1970-01-01
    • 2011-09-26
    相关资源
    最近更新 更多