How do I debug/troubleshoot an event not firing? - c#

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>

Related

Bind same command to datagrid double click

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.

WPF Command not executed when viewmodel changes

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>

Change SelectedItem within SelectionChanged-Event Command

I have a DataGrid with the SelectedItem bound to a property in my ViewModel. A Command is executed on the SelectionChanged-Event:
<DataGrid ItemsSource="{Binding MyDataList}" SelectedItem="{Binding MySelectedItem}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding MyCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</DataGrid>
In MyCommand under certain circumstances I want to set the DataGrid.SelectedItem to the value it was before the Selection was changed. But the selection highlighting in the DataGrid does not change nevertheless.
Is it possible to prevent ("Handled = true;") the SelectionChanged-Event in the attached Command?

call functions of viewModel from user control

I have View1, ViewModel1 (which is DataSource for View1) and UserControl (TextBlockComboBoxUC).
View1 contains TextBlockComboBoxUC in XAML like this :
<vwKomp:TextBlockComboBoxUC
ComboBoxItemSource="{Binding Path=ZoznamStatov, Mode=OneWay}"
ComboBoxSelectedValue="{Binding Path=TrvalaAdresa.Stat, Mode=TwoWay}">
</vwKomp:TextBlockComboBoxUC>
TextBlockComboBoxUC contains TextBlock and ComboBox.
How can I call the method from ViewModel1 when ComboBox's SelectionChanged event is raised?
I suppose somehow via delegates, but I have no information about UserControl in ViewModel1.
If you don't mind using the MVVM Light library, I think you can set up a trigger for that event to call the command:
<vwKomp:TextBlockComboBoxUC
ComboBoxItemSource="{Binding Path=ZoznamStatov, Mode=OneWay}"
ComboBoxSelectedValue="{Binding Path=TrvalaAdresa.Stat, Mode=TwoWay}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged" >
<cmd:EventToCommand
Command="{Binding YourSelectionChangedCommandHandler}"
PassEventArgsToCommand="True" />
</i:EventTrigger>
</i:Interaction.Triggers>
</vwKomp:TextBlockComboBoxUC>
Where:
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
Source: http://www.danharman.net/2011/08/05/binding-wpf-events-to-mvvm-viewmodel-commands/

WPF:How to Interaction.Triggers Add Where

<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

Categories

Resources