命令绑定到ContextMenu(在ListBox中的ListBoxItem上)不工作 [英] Command bind to ContextMenu (which on ListBoxItem in ListBox) don't work

查看:654
本文介绍了命令绑定到ContextMenu(在ListBox中的ListBoxItem上)不工作的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在WPF中,使用MVVM光,有一个 Class (由一些学生组成)和 Class 持有一些学生





右键单击学生的姓名,然后显示 MessageBox ,这样确定:



ClassDetailView.xaml

 < UserControl DataContext ={Binding ClassDetail,Source = {StaticResource Locator}}> 
< DockPanel>
< ListBox
ItemsSource ={Binding Students}
DisplayMemberPath =Name>
< ListBox.ContextMenu>
< ContextMenu DataContext ={Binding Path = PlacementTarget,RelativeSource = {RelativeSource Self}}>
< MenuItem
Header =Show Selected
Command ={Binding Path = DataContext.RemoveStudentCommand}
CommandParameter ={Binding Path = SelectedItem}/>
< / ContextMenu>
< /ListBox.ContextMenu>
< / ListBox>
< / DockPanel>
< / UserControl>但是,它不工作在这种方式(使用ListBox.ItemContainerStyle):

 < ListBox.ItemContainerStyle> 
< Style TargetType =ListBoxItem>
< Setter Property =ContextMenu>
< Setter.Value>
< ContextMenu DataContext ={Binding Path = PlacementTarget,RelativeSource = {RelativeSource Self}}>
< MenuItem Header =Show Selected
Command ={Binding Path = DataContext.RemoveStudentCommand}
CommandParameter ={Binding Path = SelectedItem}/>
< / ContextMenu>
< /Setter.Value>
< / Setter>
< / Style>
< /ListBox.ItemContainerStyle>

而不是

 < ListBox.ContextMenu> 
< ContextMenu ...>
...
< ContextMenu />
< /ListBox.ContextMenu>

ClassDetailViewModel.cs

  namespace ContextMenu.ViewModel 
{
public class ClassDetailViewModel:ViewModelBase
{
public ClassDetailViewModel()
{
CreateData
}

public void CreateData()
{
students.Add(new StudentViewModel(){Name =QQ});
students.Add(new StudentViewModel(){Name =WW});
students.Add(new StudentViewModel(){Name =EE});
students.Add(new StudentViewModel(){Name =RR});
students.Add(new StudentViewModel(){Name =AA});
students.Add(new StudentViewModel(){Name =SS});
students.Add(new StudentViewModel(){Name =DD});
students.Add(new StudentViewModel(){Name =FF});
students.Add(new StudentViewModel(){Name =ZZ});
students.Add(new StudentViewModel(){Name =XX});
}

public const string StudentsPropertyName =Students;
private ObservableCollection< StudentViewModel> students =
new ObservableCollection< StudentViewModel>();
public ObservableCollection< StudentViewModel>学生
{
get {return students; }
set
{
if(students == value){return; }
students = value;
RaisePropertyChanged(StudentsPropertyName);
}
}

private RelayCommand< StudentViewModel> removeStudentCommand;
public RelayCommand< StudentViewModel> RemoveStudentCommand
{
get
{
return removeStudentCommand
? (removeStudentCommand =
new RelayCommand< StudentViewModel>(ExecuteRemoveStudentCommand));
}
}
private void ExecuteRemoveStudentCommand(StudentViewModel student)
{
if(null == student){return; }
MessageBox.Show(string.Format(RemoveStudent:{0},student.Name));
}
}
}

StudentViewModel.cs

 命名空间ContextMenu.ViewModel 
{
public class StudentViewModel:ViewModelBase
{
public const string NamePropertyName =Name;
private string name =;
public string Name
{
get {return name; }
set
{
if(name == value){return; }
name = value;
RaisePropertyChanged(NamePropertyName);
}
}
}
}


解决方案

您可以使用上下文菜单作为资源吗?



类似:

 < UserControl.Resources> 

< ContextMenu x:name =contextMenuExampleDataContext ={Binding Path = PlacementTarget,RelativeSource = {RelativeSource Self}}
< MenuItem Header =Show Selected
Command ={Binding Path = DataContext.RemoveStudentCommand}
CommandParameter ={Binding Path = SelectedItem}/>
< / ContextMenu>
< /UserControl.Resources>

然后在列表上,执行以下操作:

 < Listbox ContextMenu = {StaticResource contextMenuExample} ... /> 

或者你真的想使用ItemContainerStyle吗?



从 - > 如何右键单击列表框中的项目并打开WPF上的菜单

 < ListBox Name =someListBoxMouseDown =someListBox_MouseDown> 
< ListBox.Resources>

<! - 定义一个上下文菜单 - >
< ContextMenu x:Key =MyElementMenu>
< MenuItem Header =DeleteClick =MenuItemDelete_Click/>
< / ContextMenu>

<! - 为当前ListBox中的每个ListBoxItem设置一个上下文菜单 - >
< Style TargetType ={x:Type ListBoxItem}>
< Setter Property =ContextMenuValue ={StaticResource MyElementMenu}/>
< / Style>

< /ListBox.Resources>
< ListBoxItem> ...< / ListBoxItem>
< ListBoxItem> ...< / ListBoxItem>
< ListBoxItem> ...< / ListBoxItem>
< / ListBox>


In WPF, with MVVM light, there's a Class(which is consist of some students), and the Class hold some Students.

Right-Click one Student's name, then will show a MessageBox, it is ok in this way:

ClassDetailView.xaml

<UserControl DataContext="{Binding ClassDetail, Source={StaticResource Locator}}">
    <DockPanel>
        <ListBox 
            ItemsSource="{Binding Students}" 
            DisplayMemberPath="Name">
            <ListBox.ContextMenu>
                <ContextMenu DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
                    <MenuItem 
                        Header="Show Selected" 
                        Command="{Binding Path=DataContext.RemoveStudentCommand}"
                        CommandParameter="{Binding Path=SelectedItem}"/>
                </ContextMenu>
            </ListBox.ContextMenu>
        </ListBox>
    </DockPanel>
</UserControl>

But, it don't work in this way (use ListBox.ItemContainerStyle):

<ListBox.ItemContainerStyle>
    <Style TargetType="ListBoxItem">
        <Setter Property="ContextMenu">
            <Setter.Value>
                <ContextMenu DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
                    <MenuItem Header="Show Selected" 
                            Command="{Binding Path=DataContext.RemoveStudentCommand}"
                            CommandParameter="{Binding Path=SelectedItem}"/>
                 </ContextMenu>
             </Setter.Value>
         </Setter>
     </Style>
 </ListBox.ItemContainerStyle>

instead of

<ListBox.ContextMenu>
    <ContextMenu ...>
        ...
    <ContextMenu />
</ListBox.ContextMenu>

ClassDetailViewModel.cs

namespace ContextMenu.ViewModel
{
    public class ClassDetailViewModel : ViewModelBase
    {
        public ClassDetailViewModel()
        {
            CreateData();
        }

        public void CreateData()
        {
            students.Add(new StudentViewModel() { Name = "QQ" });
            students.Add(new StudentViewModel() { Name = "WW" });
            students.Add(new StudentViewModel() { Name = "EE" });
            students.Add(new StudentViewModel() { Name = "RR" });
            students.Add(new StudentViewModel() { Name = "AA" });
            students.Add(new StudentViewModel() { Name = "SS" });
            students.Add(new StudentViewModel() { Name = "DD" });
            students.Add(new StudentViewModel() { Name = "FF" });
            students.Add(new StudentViewModel() { Name = "ZZ" });
            students.Add(new StudentViewModel() { Name = "XX" });
        }

        public const string StudentsPropertyName = "Students";
        private ObservableCollection<StudentViewModel> students = 
            new ObservableCollection<StudentViewModel>();
        public ObservableCollection<StudentViewModel> Students
        {
            get { return students; }
            set
            {
                if (students == value) { return; }
                students = value;
                RaisePropertyChanged(StudentsPropertyName);
            }
        }

        private RelayCommand<StudentViewModel> removeStudentCommand;
        public RelayCommand<StudentViewModel> RemoveStudentCommand
        {
            get
            {
                return removeStudentCommand
                    ?? (removeStudentCommand =
                        new RelayCommand<StudentViewModel>(ExecuteRemoveStudentCommand));
            }
        }
        private void ExecuteRemoveStudentCommand(StudentViewModel student)
        {
            if (null == student) { return; }
            MessageBox.Show(string.Format("RemoveStudent:{0}", student.Name));
        }
    }
}

StudentViewModel.cs

namespace ContextMenu.ViewModel
{
    public class StudentViewModel : ViewModelBase
    {
        public const string NamePropertyName = "Name";
        private string name = "";
        public string Name
        {
            get { return name; }
            set
            {
                if (name == value) { return; }
                name = value;
                RaisePropertyChanged(NamePropertyName);
            }
        }
    }
}

解决方案

Can you use the contextmenu as a resource?

Something like:

<UserControl.Resources>

<ContextMenu x:name="contextMenuExample" DataContext="{Binding Path=PlacementTarget, RelativeSource={RelativeSource Self}}">
                    <MenuItem Header="Show Selected" 
                            Command="{Binding Path=DataContext.RemoveStudentCommand}"
                            CommandParameter="{Binding Path=SelectedItem}"/>
                 </ContextMenu>
</UserControl.Resources>

Then on list, do something like:

<Listbox ContextMenu = {StaticResource contextMenuExample} ... />

Or do you really want to use ItemContainerStyle?

from -> how to right click on item from Listbox and open menu on WPF

<ListBox Name="someListBox" MouseDown="someListBox_MouseDown">
    <ListBox.Resources>

        <!--Defines a context menu-->
        <ContextMenu x:Key="MyElementMenu">
            <MenuItem Header="Delete" Click="MenuItemDelete_Click"/>
        </ContextMenu>

        <!--Sets a context menu for each ListBoxItem in the current ListBox-->
        <Style TargetType="{x:Type ListBoxItem}">
             <Setter Property="ContextMenu" Value="{StaticResource MyElementMenu}"/>
        </Style>

    </ListBox.Resources>
    <ListBoxItem>...</ListBoxItem>
    <ListBoxItem>...</ListBoxItem>
    <ListBoxItem>...</ListBoxItem>
</ListBox>

这篇关于命令绑定到ContextMenu(在ListBox中的ListBoxItem上)不工作的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆