当通过样式设置器设置上下文菜单时,PlacementTarget属性为空。

5
在我的应用程序中,我有一个视图(ListView)和一个视图模型。在视图模型内部,我有两个属性:第一个是项目列表,第二个是命令。我想在ListView中显示来自第一个属性的项目。此外,我希望为每个项目都有一个上下文菜单,单击它将激活第二个属性的命令。
以下是我的视图模型代码:
public class ViewModel
{
    public IEnumerable Items
    {
        get
        {
            return ...;  //returns a collection of items
        }
    }

    public ICommand MyCommand //this is a command, I want to be able execute from context menu of each item
    {
        get
        {
            return new DelegateCommand(new Action<object>(delegate(object parameter)
            {
                //here code of the execution   
            }
            ), new Predicate<object>(delegate(object parameter)
            {
                //here code of "can execute"
            }));
        }
    }

现在是XAML部分:
<ListView  ItemsSource="{Binding Items}">
<ListView.Resources>
    <commanding:CommandReference x:Key="myCommand" Command="{Binding MyCommand}"/>
</ListView.Resources>
    <ListView.ItemTemplate>
        <DataTemplate>
            <TextBlock 
                    Text="{Binding Name}"
                    />
        </DataTemplate>
    </ListView.ItemTemplate>
    <ListView.ItemContainerStyle>
        <Style TargetType="{x:Type ListViewItem}">
            <Setter Property="ContextMenu">
                <Setter.Value>
                    <ContextMenu>
                        <MenuItem 
                            Header="Remove from workspace" 
                            Command="{StaticResource myCommand}"
                            CommandParameter="HERE I WANT TO PASS THE DATA CONTEXT OF THE ListViewItem"
                            />
                    </ContextMenu>
                </Setter.Value>
            </Setter>
        </Style>
    </ListView.ItemContainerStyle>
</ListView>

问题:直到我实际打开上下文菜单,上下文菜单的PlacementTarget为null。在命令的“CanExecute”被调用之前,我需要以某种方式将所单击的ListViewItem的数据上下文接收到 - 我真的希望所有内容都在XAML中完成,而不需要处理任何代码后台回调。
提前感谢您。
1个回答

1
如果你正在寻找 ListViewItem 的 DataContext,你可以这样做: CommandParameter="{Binding}" 编辑 - 这是我尝试过的:
public partial class MainWindow : Window
{
    private ObservableCollection<Person> list = new ObservableCollection<Person>();

    public MainWindow()
    {
        InitializeComponent();
        list.Add(new Person() { Name = "Test 1"});
        list.Add(new Person() { Name = "Test 2"});
        list.Add(new Person() { Name = "Test £"});
        list.Add(new Person() { Name = "Test 4"});
        this.DataContext = this;

    }

    public static ICommand MyCommand //this is a command, I want to be able execute from context menu of each item     
    {         
        get
        {
            return new DelegateCommand<Person>(
                a => Console.WriteLine(a.Name),
                a => true);
        }
    }

    public ObservableCollection<Person> Items
    {
        get
        {
            return this.list;
        }
    }
}

public class Person
{
    public string Name { get; set; }
}

而且xaml:

<Window x:Class="ListView1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:ListView1="clr-namespace:ListView1" Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListView ItemsSource="{Binding Items}">            
            <ListView.ItemTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding Name}" />
                </DataTemplate>
            </ListView.ItemTemplate>
            <ListView.ItemContainerStyle>
                <Style TargetType="{x:Type ListViewItem}">
                    <Setter Property="ContextMenu">
                        <Setter.Value>
                            <ContextMenu>
                                <MenuItem Header="Remove from workspace" Command="{x:Static ListView1:MainWindow.MyCommand}"  CommandParameter="{Binding}" />
                            </ContextMenu>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListView.ItemContainerStyle>
        </ListView>
    </Grid>
</Window>

由于ContextMenu具有自己的可视树,因此数据上下文为空。 - Illidan
1
你完全复制了我的XAML,并在命令的“CanExecute”中接收到对象?这非常奇怪。 - Illidan
anivas,你错误地复制了我的示例,这帮助我找到了问题。在我的代码中,命令不是静态的,所以我无法通过静态标记扩展获取它。相反,我使用CommandReference类来获取我的命令。当我看到你的代码可以工作而我的不能时,我明白了问题所在。现在我知道该查找什么了——谷歌的第二个结果显示了以下文章:http://social.msdn.microsoft.com/Forums/eu/wpf/thread/232c3a82-8c49-45e8-a627-5d061b97f4f6——解释了CommandReference的CanExecuteChanged问题。谢谢) - Illidan

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