【问题标题】:WPF MVVM - Command binding inside of an ItemsControlWPF MVVM - ItemsControl 内的命令绑定
【发布时间】:2010-11-06 06:54:47
【问题描述】:

我目前正在将一个小型 WPF 项目转换为 MVVM。我的 ItemsControl 绑定到的主窗口的 ViewModel 中有一个List<CustomObject>,并使用 DataTemplate 来构建每个元素的 UI。我的旧代码使用 DataTemplate 中的事件处理程序来处理单击事件。我想使用某种命令绑定来消除我的代码隐藏事件处理程序,但我的 ItemsControl 中项目的 DataContext 是模型对象,因此我目前无法从 ViewModel 绑定到 ICommand。

所以,我想有几种方法可以解决这个问题,我不确定哪种方法是最“MVVM”的方法。我是否将 ItemsControl.ItemsSource 绑定到代表每个项目的新 ViewModel 类的集合?或者我是否使用 UserControls 而不是 DataTemplate,然后我可以将每个 UserControl 绑定到它自己的代表它的 ViewModel 实例?或者是否有某种绑定表达式我可以用来引用窗口的 DataContext 以访问绑定到 ViewModel(当我输入这个时,它听起来很糟糕,所以我假设一个很大的“NO”想法)?

另外,我想将我的命令绑定到 Grid 控件的 LeftMouseButtonUp 事件。网格没有“命令”,所以我试图使用 InputBindings。我可以使用静态命令(例如内置的 ApplicationCommands 之一),但我不能使用绑定表达式绑定到作为 ViewModel 属性的 ICommand 实例,因为 MouseBinding.Command 不是 DependencyProperty。

我对 MVVM 中的事件处理主题感到很困惑,因此感谢所有信息。

【问题讨论】:

    标签: .net wpf mvvm


    【解决方案1】:

    我是否将 ItemsControl.ItemsSource 绑定到代表每个项目的新 ViewModel 类的集合?

    您是创建一个 CustomObjectViewModel 来承载命令还是将命令放在具有列表的同一个 ViewModel 中,实际上取决于发生的操作的功能。它是属于 CustomObject 的东西,还是属于你当前的 ViewModel 的东西?

    或者是否有某种绑定表达式我可以用来引用窗口的 DataContext 以访问绑定到 ViewModel(当我输入这个时,它听起来很糟糕,所以我假设一个很大的“NO ” 对这个想法)?

    这并不像听起来那么糟糕。您实际上并不需要 Window 的 DataContext,只需要它切换到各个项目之前的 DataContext。因此,如果您的命令位于托管 CustomObjects 列表的同一 ViewModel 上,则可以使用以下任一方法从 CustomObject 的 DataTemplate 中绑定到它:

    {Binding ElementName=uiCustomObjectsItemsControl, Path=DataContext.MyCommand}
    {Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ItemsControl}}, Path=DataContext.MyCommand}
    

    另外,我想绑定我的命令 to 是 a 的 LeftMouseButtonUp 事件 网格控制。没有“命令” 一个网格,所以我试图使用 输入绑定。

    为此,我会使用 Attached Command Behaviors 之类的东西,它可以让您将 ICommand 附加到任何事件。

    【讨论】:

      【解决方案2】:

      Josh Smith 在 MSDN here 上写了一篇出色的文章,他谈到了命令绑定。

      在你的情况下,归结为:

      • 您不会消除所有代码隐藏,但它可能看起来会有所不同
      • 您的 CustomObjects 可能必须具有 VM shim 类,或者是 VM 本身才能利用他描述的 RelayCommand 架构。

      HTH。

      【讨论】:

        【解决方案3】:

        您可以尝试将您的命令保留在您的模型中。

        public class MyModel
        {
            public MyModel()
            {
                MyCommand = new DelegateCommand(MyCommandExecute);
            }
        
            public ICommand MyCommandCommand { get; set; }
        
            private void MyCommandExecute()
            {
            }
        }
        

        然后,您的 ViewModel 中的项目列表必须有一个 ObservableList,

        public class MyViewModel
        {
            public MyViewModel()
            {
                MyStarterCommand = new DelegateCommand(MyCommandExecute);
        
                if (!IsDesignTime)//(bool)DependencyPropertyDescriptor.FromProperty(DesignerProperties.IsInDesignModeProperty, typeof(DependencyObject)).Metadata.DefaultValue;
                    MyCommand.Execute(null);
            }
        
            private ObservableCollection<MyModel> list;
            private  ICommand MyStarterCommand { get; set; }
        
            public ObservableCollection<MyModel> List
            {
                get { return list; }
                set
                {
                    list = value;
                    RaisePropertyChanged(() => List);
                }
            }
        
            private void MyStarterCommandExecute()
            {
                List = new ObservableCollection<MyModel>();
        
                //Fill the list here
                List.Add(new MyModel());
            }
        }
        

        那么在 XAML 中你必须说;

        <ItemsControl ItemsSource="{Binding List}">
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <Button Content="MyButton" Command="{Binding MyCommand}" />
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 2021-11-05
          • 2021-08-29
          • 1970-01-01
          • 1970-01-01
          • 2018-11-20
          • 1970-01-01
          • 2014-10-21
          • 1970-01-01
          相关资源
          最近更新 更多