I'm new to WPF and I don't know why binding from the viewmodel does not execute the specified command.
<CheckBox x:Name="CheckBoxName" Content="MyCheckBox" IsChecked="{Binding Restrictions.MyCheckBox}" Command="{Binding MyCommand}" CommandParameter="{Binding ElementName=CheckBoxName}"/>
When I check the checkbox in the view, MyCommand is executed as expected, but when I set the IsChecked property from the viewmodel using binding, the command is not executed.
Does anyone have any idea why it's happening? How can I execute the command from viewmodel using binding?
Thanks you very much!
As far as I know, the Command is executed on the "Click" event of the base "ButtonBase" class, which is not triggered if you change the IsChecked Property via Binding.
One solution would be to attach a trigger to the Checked and Unchecked event, which triggers your command.
First you need to add the namespace
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
And for your checkbox
<CheckBox x:Name="CheckBoxName"
Content="MyCheckBox"
IsChecked="{Binding Restrictions.MyCheckBox}"
Command="{Binding MyCommand}"
CommandParameter="{Binding ElementName=CheckBoxName}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding MyCommand}" CommandParameter="{Binding Path=IsChecked, ElementName=CheckBoxName}" />
</i:EventTrigger>
<i:EventTrigger EventName="Unchecked">
<i:InvokeCommandAction Command="{Binding MyCommand}" CommandParameter="{Binding Path=IsChecked, ElementName=CheckBoxName}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Checkbox>
Related
I have a menu item that is configured to execute a command using binding:
<MenuItem Margin="2"
Header="Process something"
Command="{Binding SomethingCommand}"
IsEnabled="{Binding SomethingIsEnabled}">
</MenuItem>
It also configure if this item is enabled or not.
Now, I need to execute the same command when user double click a row in datagrid and only when "SomethingisEnabled" is true.
How to configure datagrid to do that?
setup xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" in xaml
<DataGrid x:Name="dataGrid" ItemsSource="{Binding DataList}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding SomethingCommand}" CommandParameter="{Binding ElementName=dataGrid, Path=SelectedItem}"></i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
This will call a relaycommand SomethingCommand and pass the selected item (if any, otherwise null) on the doubleclicked grid.
The following Xaml code allows me to use a context menu in a listview and send the row details as an object to the view model:
<ListView.ContextMenu>
<ContextMenu>
<MenuItem Header="Link This Operation"
Command="{Binding SelectedOperation}"
CommandParameter="{Binding RelativeSource={RelativeSource AncestorType=ContextMenu}, Path=PlacementTarget.SelectedItem}"/>
</ContextMenu>
</ListView.ContextMenu>-->
However i want to do the same thing through a double mouse click. I have tried all sorts. Including this:
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding SelectedItem}"
CommandParameter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=PlacementTarget.SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
This works but the object is always null.
Any ideas?
Try this one:
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<i:InvokeCommandAction Command="{Binding SelectedOperation}"
CommandParameter="{Binding RelativeSource={RelativeSource Self}, Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
I tried with
<RadioButton Content="Boom" Command={Binding MyCommand} IsEnabled="{Binding IsChecked, Converter={StaticResource InverseBooleanConverter}, RelativeSource={RelativeSource Mode=Self}}"/>
but nothing happens. Why is that and how to fix it?
Step 1: Add System.Windows.Interactivity reference
Step 2: Add Namespace in XAML xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
Step 3:
<RadioButton Content="Boom" IsEnabled="{Binding IsChecked, Converter={StaticResource InverseBooleanConverter}, RelativeSource={RelativeSource Mode=Self}}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Checked">
<i:InvokeCommandAction Command="{Binding MyCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</RadioButton>
The following code works as expected:
<RadioButton Content="Boom" Command="{Binding MyCommand}" />
That is, as in case of a regular Button, MyCommand is fired every time you click a RadioButton. If you're using RadioButtons, this, understandably, may not be what you want.
More useful will be passing some sort of data as a CommandParameter to know which option was checked:
<RadioButton Content="AAA" Command="{Binding MyCommand}" CommandParameter="AAA" GroupName="MyGroup"/>
<RadioButton Content="BBB" Command="{Binding MyCommand}" CommandParameter="BBB" GroupName="MyGroup"/>
Example command method:
private ICommand _MyCommand;
public ICommand MyCommand
{
get { return _MyCommand ?? (_MyCommand = new DelegateCommand(a => MyCommandMethod(a))); }
}
private void MyCommandMethod(object item)
{
Console.WriteLine("Chosen element: " + (string)item);
}
In one of my views, I have 2 event triggers on a TabControl:
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<cmd:EventToCommand Command="{Binding TestCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="TabClosed">
<cmd:EventToCommand Command="{Binding CloseCurrentWorkspaceCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Here is the code for the command bindings:
RelayCommand _t;
public RelayCommand TestCommand { get { return _t ?? (_t = new RelayCommand(foo)); } }
void foo()
{
// This is just to see if the event is firing.
System.Windows.MessageBox.Show("Fired");
}
RelayCommand _closeWorkspaceCommand;
public RelayCommand CloseCurrentWorkspaceCommand
{
get { return _closeWorkspaceCommand ?? (_closeWorkspaceCommand = new RelayCommand(CloseWorkspace)); }
}
void CloseWorkspace()
{
// Workspaces is a ObservableCollection<WorkspaceViewModel>
Workspaces.Remove(SelectedItem);
}
The SelectedItemChanged event never fires when the selected item (or index) is changed. Also changing the event to SelectedIndexChanged has no effect. The TabClosed event fires without a problem. The SelectedIndex and SelectedItem bindings are updating accordingly.
I've checked the output Window and I don't see any binding errors or anything that might suggest the binding is wrong.
How can I start to diagnose why this event won't fire?
Full code of control:
<wpf:TabControlExt Grid.Row="1"
ItemsSource="{Binding Workspaces}"
SelectedItem="{Binding SelectedItem}"
SelectedIndex="{Binding SelectedIndex}">
<wpf:TabControlExt.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Header, Mode=TwoWay}"/>
</DataTemplate>
</wpf:TabControlExt.ItemTemplate>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectedItemChanged">
<cmd:EventToCommand Command="{Binding TestCommand}"/>
</i:EventTrigger>
<i:EventTrigger EventName="TabClosed">
<cmd:EventToCommand Command="{Binding CloseCurrentWorkspaceCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</wpf:TabControlExt>
Fixed it.
It turns out I was binding to the wrong event. I should have been binding to SelectionChanged. I only found this out when going through the Triggers pane in Blend. It didn't give me the option to pick SelectedIndexChanged or SelectedItemChanged.
Although in hindsight, SelectionChanged makes more sense since when the item changes, the index changes, and you can't rearrange tabs in the control as far as I know.
So the correct code is:
<i:EventTrigger EventName="SelectionChanged">
<cmd:EventToCommand Command="{Binding TestCommand}"/>
</i:EventTrigger>
<StackPanel>
<TextBox Text="" x:Name="input"/>
<Button Content="Click">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click"><!-- TextBox has to contain "ABC" to get Button Click enabled this event-->
<i:InvokeCommandAction Command="{Binding OnAdd}" CommandParameter="1"></i:InvokeCommandAction>
</i:EventTrigger>
<i:EventTrigger EventName="Click"><!-- TextBox has to contain "123" to get Button Click enabled this event-->
<i:InvokeCommandAction Command="{Binding OnAdd2}" CommandParameter="1"></i:InvokeCommandAction>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</StackPanel>
I want the <i:EventTrigger EventName="Click"> TextBox has to contain "ABC" to get Button Click enabled this event
I would suggest you do this handling within your OnAdd Command. Look especially for the CanExecute Method. This one handles if you Button will be enabled or not. You can read here how to implement this :
Commands Tutorial