|
<pre lang="text">
1.How to bind the MenuItem Command of ListBoxItem ContextMenu dynamically?
2. How to set its CommandParameter?
//----------------------------------
//MainWindowView.xaml
//----------------------------------
<Window x:Class="MVVM.Views.MainWindowView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
xmlns:vm="clr-namespace:MVVM.ViewModels"
Title="MainView" Height="354" Width="520">
<Window.DataContext>
<vm:MainWindowViewModel/>
</Window.DataContext>
<Grid>
<!--In this ListBox, the MenuItem command can not be called-->
<ListBox Height="252" HorizontalAlignment="Left" Margin="12,51,0,0" Name="listBox1" VerticalAlignment="Top" Width="201"
ItemsSource="{Binding Path=TestItems}">
<ListBox.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding}" Width="150">
<TextBlock.ContextMenu>
<ContextMenu>
<MenuItem Header="Call Command1" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Command1}" CommandParameter="???"/><!--here the Command1 not be called-->
</i:EventTrigger> <!--how to set command parameter to this ListBoxItem displaying text?-->
</i:Interaction.Triggers>
</MenuItem>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<!--In this ListBox, the menuitem command can be called,
but the command parameter can not be set correctly-->
<ListBox Height="252" HorizontalAlignment="Left" Margin="230,51,0,0" Name="listBox2" VerticalAlignment="Top" Width="229"
SelectedItem="{Binding SelectedText,Mode=OneWayToSource}">
<ListBoxItem>
<TextBlock Text="item1" Name="tb" />
<ListBoxItem.ContextMenu>
<ContextMenu>
<MenuItem Header="Call Comand1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<!--this one can be called correctly,
but the command parameter can not be set correctly-->
<i:InvokeCommandAction Command="{Binding Command1}" CommandParameter="{Binding ElementName=tb,Path=Text}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</MenuItem>
</ContextMenu>
</ListBoxItem.ContextMenu>
</ListBoxItem>
<ListBoxItem>
<TextBlock Text="item2"/>
<ListBoxItem.ContextMenu>
<ContextMenu>
<MenuItem Header="Call Comand1">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Command1}" CommandParameter="" />
</i:EventTrigger>
</i:Interaction.Triggers>
</MenuItem>
</ContextMenu>
</ListBoxItem.ContextMenu>
</ListBoxItem>
</ListBox>
<Label Content="This one can not work" Height="28" HorizontalAlignment="Left" Margin="12,25,0,0" Name="label1" VerticalAlignment="Top" />
<Label Content="This one can work" Height="28" HorizontalAlignment="Left" Margin="230,25,0,0" Name="label2" VerticalAlignment="Top" />
<Label Content="Test ListBox ContextMenu" Height="28" HorizontalAlignment="Left" Margin="12,0,0,0" Name="label3" VerticalAlignment="Top" />
</Grid>
</Window>
//------------------
//MainWindowViewModel.cs
//---------------
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Input;
using System.Windows;
using System.Windows.Controls;
using MVVM.Command;
namespace MVVM.ViewModels
{
public class MainWindowViewModel : ViewModelBase
{
public List<string> TestItems
{
get
{
return new List<string>()
{
"Item1",
"Item2",
"Item3"
};
}
}
public ListBoxItem SelectedText
{
get;
set;
}
public MainWindowViewModel()
{
}
private ICommand _command1;
public ICommand Command1
{
get
{
if(null==_command1)
{
_command1 = new DelegateCommand<string>((str) =>
{
MessageBox.Show("Command1 with parameter:" + str+((TextBlock)SelectedText.Content).Text);
});
}
return _command1;
}
}
ICommand _command2;
public ICommand Command2
{
get
{
if (null == _command2)
{
_command2 = new DelegateCommand<Button>((button) =>
{
if (null == button)
return;
Point p = Mouse.GetPosition(button);
button.Content = string.Format("{0},{1}", p.X, p.Y);
});
}
return _command2;
}
}
}
}
</pre>
|
|
|
|
|
You have to either bind it to a property in your list item object, or to a static property or hard code it. In your case, you can also just specify "{Binding}" in the command parameter and it will pass in the actual object.
|
|
|
|
|
Thank you very much, SledgeHammer01.
My issue is the ListBox1 MenuItem Command binded in ListBoxItem ContextMenu MenuItem does not work. But MenuItem Command in ListBox2 can work well.
I don't know why. In my project, I need dynamically bind the menu itms just like in ListBox1 used.
Could you please help check it? thanks a lot.
|
|
|
|
|
Oh... I see what you are asking. Yeah, you're doing it wrong in both cases. You should use the ItemsSource property of the listbox to set the collection of items. There is no need to use the ItemTemplate if all you are doing is showing a TextBlock as that is the default behavior. You should specify the context menu on the ListBoxItem, not the TextBlock. Then you can use {Binding} to pass in the item itself, but it will not be necessary as the sender will be the item.
|
|
|
|
|
Thanks a lot.
I'm newer for WPF binding. I tried and tried again. And the MenuItem command in listbox1 still can not be fired.
|
|
|
|
|
Well, post your corrected code.
|
|
|
|
|
Do you have email? I can send you my demo version to you. Thanks a lot.
my email is neighbornet@163.com
|
|
|
|