WPF ItemsControl 无法绑定命令

Posted

技术标签:

【中文标题】WPF ItemsControl 无法绑定命令【英文标题】:WPF ItemsControl can't bind Command 【发布时间】:2021-11-05 07:13:39 【问题描述】:

我是 wpf 的新手,我知道这个问题已经在其他时候被问过,我尝试实施一些我找到的解决方案。但它不起作用。我做错了什么,但我看不到它是什么。 我创建了一个新的简单应用程序来测试这个问题。

namespace WpfApp3

    public class MyElement
    
        public string Text  get; set; 
        public MyElement(string t)
        
            Text = t;
        
    

    public class MyCommand : ICommand
    
        public bool CanExecute(object parameter)
        
            return true;
        
        public event EventHandler CanExecuteChanged;
        public void Execute(object parameter)
        
            _handler(parameter);
        

        private Action<object> _handler;
        public MyCommand(Action<object> handler)  _handler = handler; 
    

    public class MyItemsControlViewModel
    
        ObservableCollection<MyElement> _items;
        public ObservableCollection<MyElement> MyElementItems  get  return _items;  set  _items = value; RaisePropertyChanged("MyElementItems");  
        ObservableCollection<MyElement> _temporayList;
       
        private ICommand _itemClicked;
        public ICommand ItemClicked  get  return _itemClicked;  

        public MyItemsControlViewModel()
        
            _items = new ObservableCollection<MyElement>();
            _temporayList = new ObservableCollection<MyElement>();
            _itemClicked = new MyCommand(OnItemSelected);

            AddItem("Element 1");
            AddItem("Element 2");
            AddItem("Element 3");
            UpdateList();
        

        public void UpdateList()
        
            MyElementItems = _temporayList;
        
        public void AddItem(string t)
        
            MyElement item = new MyElement(t);
            _temporayList.Add(item);
        

        public void OnItemSelected(object param)
        
            Debug.WriteLine("Executed!");
        
        public event PropertyChangedEventHandler PropertyChanged;
        private void RaisePropertyChanged(string propertyName)
        
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        
    
    

XAML

<UserControl x:Class="WpfApp3.MyUserControl"
                  xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                  xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                  xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                  xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                   xmlns:local="clr-namespace:WpfApp3"
                  mc:Ignorable="d" 
                  d:DesignHeight="1080" d:DesignWidth="570"
                  x:Name="myCustomControl">
    <Grid >
        <Button x:Name="btnOutsideItemsControl"  Width="100" Height="100 " VerticalAlignment="Top" Command="Binding ItemClicked" />
        <ItemsControl 
            x:Name="listItems"             
            ScrollViewer.PanningMode="None"
            IsEnabled="False"
            Background = "Transparent"         
            HorizontalAlignment="Center"
            ItemsSource="Binding MyElementItems" Margin="0,152,0,0" Width="549">
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <WrapPanel HorizontalAlignment="Left" Margin="50,0,0,0" 
                                        Background="Transparent" Orientation="Vertical"/>
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <ItemsControl.ItemTemplate>
            <DataTemplate>
                <Button 
                    Content="Binding Text"
                    Command="Binding ElementName=listItems, Path=DataContext.ItemClicked"/>

            </DataTemplate>
            </ItemsControl.ItemTemplate>    
        </ItemsControl>
    </Grid>
</UserControl>

该组件在 MainWindow.xaml 中使用。

namespace WpfApp3

    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : Window
    
        private MyItemsControlViewModel _myViewModel;
        public MyItemsControlViewModel MyViewModel  get  return _myViewModel;  
        public MainWindow()
        
            _myViewModel = new MyItemsControlViewModel();
            InitializeComponent();

            myCustomControl.DataContext = MyViewModel;
        
    

XAML

<Window x:Class="WpfApp3.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:local="clr-namespace:WpfApp3"
        mc:Ignorable="d"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <local:MyUserControl x:Name="myCustomControl"/>
    </Grid>
</Window>

当我运行应用程序时,我可以正确地看到包含正确文本的 3 项列表。 但是,如果我单击列表中的一个按钮,我将看不到 Debug.WriteLine("Executed!");

的输出

但是,如果我单击 ItemsControl 之外的按钮 btnOutsideItemsControl,它就可以工作。我可以看到 Debug.WriteLine("Executed!"); 的输出 所以我认为命令的定义也是正确的。

要正确绑定 ItemsControl 内 Button 的 Command 属性,我试试这个

<Button Command="Binding ElementName=listItems, Path=DataContext.ItemClicked">

还有这个

<Button Command="Binding DataContext.ItemClicked, RelativeSource=RelativeSource Mode=FindAncestor,AncestorType=ItemsControl">

但它不起作用。

请帮忙!

【问题讨论】:

这令人困惑。视图模型有一个空的 OnItemSelected 方法,该方法应该由 ItemClicked 执行,但您正在谈论的是 OnMyItemSelected 方法。哪里是?尝试将您的代码减少到最小的可重现示例。删除与问题无关的内容。 请注意,UpdateList() 不会通知 UI,因为您设置了支持字段,而不是属性 MyElementItems 感谢@Clemens 的回复和建议。我改变了问题。我创建了一个新的应用程序 WpfApp3 并添加了查看我的问题所需的最少代码。如果仍然感到困惑,请告诉我。谢谢! 【参考方案1】:

一旦我告诉你,你会踢自己的。

您的问题是您在ItemsControl 上设置了IsEnabled="False"。删除它,宇宙就会一切顺利。

【讨论】:

是的,我绝对想踢自己!我不知道我怎么没看到!非常感谢

以上是关于WPF ItemsControl 无法绑定命令的主要内容,如果未能解决你的问题,请参考以下文章

wpf异常:某个ItemsControl与它的项源不一致

ItemsControl 中 DataTemplate 中的 WPF UserControl - 如何绑定到 ItemsSource 的父级

WPF: WrapPanel 容器的模板数据绑定(ItemsControl)

在WPF中的UserControl中的ItemsControl中绑定问题

WPF CommandParameter 在第一次调用 CanExecute 时为 NULL

ItemsControl 上的 WPF MVVM 单选按钮