WPF的ItemsControl中按钮的命令绑定不起作用

3
我有一个ItemsControl控件,它的ItemsSource是一个ObservableCollection。DataTemplate内部有一个按钮。该按钮的Command属性绑定到ViewModel中的RelayCommand(我使用MVVM Light),而CommandParameter则绑定到ItemsSource中对应的项。
问题在于,由于某些原因,该命令永远不会触发。代码后台正常工作。当调试鼠标单击事件处理程序时,我可以看到发送方(Button类型)具有填充了正确数据的CommandParameter,而Command为空。

我错过了什么?

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)
{

}
3个回答

23

在数据模板中使用命名元素绑定作为绑定源,以从根数据上下文访问命令。您可以使用根网格或其他容器作为命名元素。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}">
                    <!--...-->

我尝试了这个方法,它起作用了 - 但我不知道为什么必须将ElementName设置为ItemsControl名称的名称,并且为什么必须指定Path = DataContext.FOO_COMMAND。有人能帮忙解释一下吗? - Vidar

7

您需要在相对源绑定中添加“FindAncestor”:

RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}

这样可以找到最近的祖先元素类型为ItemsControl。


-2
在我看来,你应该改变你的策略,将命令放在User类中,并通过事件从该类通知视图模型。 这将简化你的XAML代码,并且在我看来,使你的视图模型更加连贯。

1
这是一个不好的想法。User,作为一个Model,不应该处理命令。 - B.K.
在这种情况下,只需使用视图模型包装用户。 - Mattia Magosso

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接