WPF ItemsControl 按钮命令绑定不起作用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32542283/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
WPF ItemsControl Button command binding not working
提问by Venom
I have an ItemsControl control that has an ObservableCollection as its ItemsSource. It also has a button located inside of its DataTemplate. The button's Command property is bound to a RelayCommand in the ViewModel (I'm using MVVM Light) and the CommandParameter is bound to the corresponding item in the ItemsSource.
The problem is that the command never fires, for some reason. Code-behind works fine, on the other hand. When debugging the mouse click event handler I can see that the sender (of type Button) has a CommandParameter filled with the correct data whereas Command is null.
我有一个 ItemsControl 控件,它有一个 ObservableCollection 作为它的 ItemsSource。它还有一个位于其 DataTemplate 内部的按钮。按钮的 Command 属性绑定到 ViewModel 中的 RelayCommand(我使用的是 MVVM Light),CommandParameter 绑定到 ItemsSource 中的相应项目。
问题是由于某种原因,该命令永远不会触发。另一方面,代码隐藏工作正常。在调试鼠标单击事件处理程序时,我可以看到发送者(按钮类型)有一个填充了正确数据的 CommandParameter,而 Command 为空。
What did I miss here?
我在这里错过了什么?
XAML:
XAML:
<ItemsControl ItemsSource="{Binding Users}"
Margin="{StaticResource ContentMargin}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Margin="{StaticResource ImageButtonMargin}"
Style="{StaticResource ImageButtonStyle}"
Command="{Binding RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}}, Path=DataContext.UserSelectedCommand}"
CommandParameter="{Binding}">
<!--...-->
ViewModel:
视图模型:
private ObservableCollection<User> _users;
private RelayCommand<User> _userSelectedCommand;
public ObservableCollection<User> Users
{
get { return _users; }
set
{
_users = value;
RaisePropertyChanged();
}
}
public RelayCommand<User> UserSelectedCommand
{
get { return _userSelectedCommand; }
}
protected override sealed void SetCommands() // called in the constructor which is in turned called by SimpleIoc
{
userSelectedCommand = new RelayCommand<User>((user) => UserSeriesSelected(user));
}
private void UserSelected(User selectedUser)
{
}
回答by loopedcode
Use named Element binding as binding source inside your data template to access commands from root data context. You can use root grid or other containers as named element. ItemsControl iteself can be used too.
使用命名元素绑定作为数据模板内的绑定源,以从根数据上下文访问命令。您可以使用根网格或其他容器作为命名元素。ItemsControl 本身也可以使用。
<ItemsControl x:Name="MyItems" ItemsSource="{Binding Users}"
Margin="{StaticResource ContentMargin}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<WrapPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Margin="{StaticResource ImageButtonMargin}"
Style="{StaticResource ImageButtonStyle}"
Command="{Binding ElementName=MyItems, Path=DataContext.UserSelectedCommand}"
CommandParameter="{Binding}">
<!--...-->
回答by Mikhail Karpov
You need to add "FindAncestor" to your relative source binding: RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ItemsControl}}
您需要将“FindAncestor”添加到您的相对源绑定中:RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type ItemsControl}}
回答by Mattia Magosso
In my opinion you should change your strategy, put the command in the Userclass and from that class notify the view-model through an event.
This is going to simplify your xaml code and, in my opinion, making your view-model more coherent.
在我看来,您应该改变策略,将命令放在User类中,然后从该类中通过事件通知视图模型。这将简化您的 xaml 代码,并且在我看来,使您的视图模型更加连贯。

