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/
Related
I'm using Microsoft.Toolkit.MVVM, in doc
we can use binding Button command like:
<Button
Content="Click me!"
Command="{Binding ButtonClickCommand}"/>
But for ListView, I have to write like with Behaviors, this code is to long:
<ListView>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectionChangedCommand}" PassEventArgsToCommand="True"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListView>
So why can't use below code instead? This is simple, but not working.
<ListView SelectionChanged={Binding SelectionChangedCommand}/>
the simple answer is the type of the object
in button Command is ICommand and in the ListView the SelectionChanged is an event and not ICommand , this why you need to use eventTrigger which is an "addon"
if you look at it from MVVM perspective the button is here to bind a command the ListView has SelectedItems collection that you can bind to and not the event , but that's more of a choice you need to make (I think that your code looks fine once you are used to it)
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.
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>
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>
In my application I have a telerik updownbox control which is used inside a telerik grid. I have a viewmodel defined, but I want to call a method of some other class which is not the viewmodel. I am trying to use CallMethodAction, but it is looking for a method in the viewmodel. Here is my code:
<telerik:GridViewDataColumn Header="{l:Translate PreloadFv}" DataMemberBinding="{Binding PreLoad,Converter={StaticResource ThreeDecimalConverter}}">
<telerik:GridViewDataColumn.CellTemplate>
<DataTemplate>
<telerik:RadNumericUpDown Value="{Binding PreLoad}">
<i:Interaction.Triggers>
<i:EventTrigger EventName="ValueChanged">
<ei:CallMethodAction TargetObject="{Binding}" MethodName="UpdateCurve"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</telerik:RadNumericUpDown>
</DataTemplate>
</telerik:GridViewDataColumn.CellTemplate>
</telerik:GridViewDataColumn>
Here I have the UpdateCurve method in some other class which is not the viewmodel. I want to call that method on ValueChanged event of the NumericUpDownBox Control. Is there any way this can be achieved?
Regards
Avik Sen