Reputation: 3563
I have something like below. For MenuItem
, here I am passing an object of that MenuItem
as a CommandParameter
. This works fine for me. My MenuItem
holds a RadioButton
and I want to use the MenuItem CommandParameter
value for this RadioButton
. Could anyone please help me how to do this. Thanks in Advance.
<MenuItem Header="Name"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Command="{Binding SortCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}">
<MenuItem.Icon>
<RadioButton VerticalAlignment="Center"
Margin="3"
IsChecked="True"
GroupName="sort"
Command="{Binding SortCommand}"
CommandParameter="..." />
</MenuItem.Icon>
</MenuItem>
Now Command
is executing only when I select the MenuItem
. I want to do the same when user selects the RadioButton
also. Below is the code which I am using for this.
public void OnSortCommandExecuted(object menuItem)
{
MenuItem menu = menuItem as MenuItem;
if (menu != null)
{
((RadioButton)menu.Icon).IsChecked = !((RadioButton)menu.Icon).IsChecked;
this.eAggregator.GetEvent<ImagesSortedEvent>().Publish(menu.Header.ToString());
}
}
Upvotes: 1
Views: 3214
Reputation: 81233
Like I said in the comments as well, it's not a good practise to pass on UI component as CommandParameter
to ViewModel since ViewModel shouldn't know about View.
I would suggest you to have proper binding in ViewModel. Create a bool
property in ViewModel and bind with IsChecked
DP of radioButton. That ways you don't have to pass any CommandParameter
from View, simply check the status of bool property from command execute method.
Now, that why
MenuItem
can't be accessed from RadioButton?
RadioButton doesn't lie in same Visual tree as that of MenuItem.
So, you can't use RelativeSource
to travel upto MenuItem. Also ElementName
binding won't work here since this to work both elements should lie in same Visual Tree.
You might find over net to use x:Reference
in such cases where two elements doesn't lie in same Visual tree but that won't work here since it will create cyclic dependency.
Last thing, you have to resort with it to use Freezable
class object to hold an instance of MenuItem and use that resource in your bindings.
First of all you need to define class deriving from Freezable
:
public class BindingProxy : Freezable
{
#region Overrides of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object),
typeof(BindingProxy));
}
and you can use it from XAML like this to pass MenuItem:
<MenuItem Header="Name"
x:Name="menuItem"
VerticalAlignment="Center"
VerticalContentAlignment="Center"
Command="{Binding SortCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}}">
<MenuItem.Resources>
<local:BindingProxy x:Key="proxy"
Data="{Binding Source={x:Reference menuItem}}"/>
</MenuItem.Resources>
<MenuItem.Icon>
<RadioButton VerticalAlignment="Center"
Margin="3"
IsChecked="True"
GroupName="sort"
Command="{Binding SortCommand}"
CommandParameter="{Binding Data.CommandParameter,
Source={StaticResource proxy}}"/>
</MenuItem.Icon>
</MenuItem>
Ofcourse you need to declare local
namespace in XAML.
PS - I would still insist to use first approach to define proper bindings in ViewModel.
UPDATE
If MenuItem
is placed under ContextMenu
, then RelativeSource
binding won't be possible. Approach described above will work in that case.
But in case you are placing MenuItem directly as child of some control (like Menu), RelativeSource
binding will work:
CommandParameter="{Binding CommandParameter,
RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=MenuItem}}"
Upvotes: 1