【发布时间】: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 并添加了查看我的问题所需的最少代码。如果仍然感到困惑,请告诉我。谢谢!
标签: c# wpf data-binding wpf-controls