Binding property PropertyChange with command that implements ICommand - c#

I am implementing MVVM pattern in wpf application. We have a textbox that calls event handler on KeyUp event. I binded text of that textbox with property tb_property which is in ViewModel. The idea that I have is to have ViewModel implement INotifyPropertyChange and to bind command object that does what event handler did and implements ICommand to the change on that tb_property. Is this a good idea, and how should I do it? I am trying to get rid of most of the events from View. Thank you in advance.

Yes, depending on what MVVM framework you are using you can bind the control's event to a iCommand on the viewmodel.
I use MVVM light so they have a build in realaycommand for just such a condition. I then bind the control's event int he following way:
add the following to your usercontrol/window opening tag (the cmd uses the mvvm framworks implementation of icommand):
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
xmlns:cmd="http://www.galasoft.ch/mvvmlight"
Then I add the command binding to the control like:
<TextBox Grid.Row="1" Text="{Binding tb_property, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
<i:Interaction.Triggers>
<i:EventTrigger EventName="YourEvent">
<cmd:EventToCommand Command="{Binding YourCommandPropertyOnVIewModel}" CommandParameter="OptionalCommandParameter"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBox>
This way you move all your "event" to your view model and I love this because other controls can use the same command.
Hope this helps
JK

Related

Handling PreviewMouseDown and PreviewMouseUp events in Prism

I have a Prism application and I'm attempting to bind PreviewMouseDown and PreviewMouseUp button events in my view to commands in my view model. When I run the code I see the following exception:
As a workaround, I'm currently binding to methods in the view and use a reference to the data context of the view model to execute the command. This works but doesn't seem correct because the view now has knowledge of the view model.
What is the proper way to handle something like this?
You cannot bind events to commands like, for example, the Command property of a button.
Luckily, you don't need to, because you have the Command property. It even disables the button if the command returns false from CanExecute.
If you have something other than a button or something other than MouseDown, you can use InvokeCommandAction (from Prism or from Interactivity)...
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDown">
<prism:InvokeCommandAction Command="{Binding MyCommand}"/>
<!-- or -->
<i:InvokeCommandAction Command="{Binding MyCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>

MVVM wpf TreeView how to handle Expanded event

I'm implementing a delayed load treeview, and need to handle the Expanded event. I would like to do it directly in the ViewModel. I have hooked up an EventTrigger:
<i:Interaction.Triggers>
<i:EventTrigger EventName="Expanded">
<interactivity:InvokeCommandAction Command="{Binding HandleExpandCmd}" TriggerParameterPath="OriginalSource" />
</i:EventTrigger>
</i:Interaction.Triggers>
While this works as expected, the OriginalSource is a TreeViewItem, and I would prefer to not include System.Windows.Controls in my ViewModel.
Alternatively, I could handle the event in code-behind, and pass the TreeViewItems's DataContext to the ViewModel. (The DataContext, of course, is what the ViewModel needs to work with.)
Is there a syntax I can use in the TriggerParameterPath that passes the TVI's DataContext, instead of the TVI itself?
Thanks ---
I would suggest to bind the TreeViewItem's IsExpanded property to one in your ViewModel. Then you can handle it in the ViewModel however you want!
Here is an example of how to do that.

Fire Prism Commands Manually

I've setup a windows store app using Prism. I have a need to use a command to notify the viewmodel of an action, but I cannot use a button in this case. Is there a way to fire a command defined in a viewmodel from the view, but in an agnostic fashion, so that the view/viewmodel aren't tightly coupled?
if(command.CanExecute(parameter))
command.Execute(parameter);
If you would like to put calling command in code behind, you can do what Aron suggested.
If you do not like code behind or it is hard to have code behind, like DataTemplate, you should think what condition to trigger the command. If you command is trigger by some event, you can use Prism like below and you also can choose some other triggers built in Prism or write trigger by yourself.
<i:Interaction.Triggers>
<i:EventTrigger EventName="FrameworkElement.Loaded">
<i:InvokeCommandAction Command="{Binding LoadCommand}" />
</i:EventTrigger>
</i:Interaction.Triggers>
If you have more complex logic, you can write a Behavior with a ICommand DependencyProperty. Binds your command on the ViewModel to the DependencyProperty and consume it in your Behavior.

Silverlight MultiBinding with a converter, converter not firing after OnPropertyChange

I'm having some issues when using a converter with multiple bindings in a Silverlight project. The task is to disable a button when it is clicked, depending how four properties are evaluated in the custom converter.
The flow of the task is as follows:
Converter fired when initialising buttons
Button clicked and Command fired in ViewModel
Keep a record of the Id of the button in one viewModel property
In ViewModel fire OnPropertyChanged for one of the three view model properties
This should fire the converter
Everything is working apart from the last step. During the second last step, I can see the Property being accessed again after the OnPropertyChanged is fired. So I can't understand why the binding doesn't pick this change up and fire the converter. I'm thinking it may be due to the button item being in a datagrid and the bindings using Path & ElementName.
I'm using a MultiBinding solution for Silverlight 5 from here.
And I've seen this question but its solution isn't available in Silverlight (Binding.IndexerName).
So on the actual control I have a datagrid where each row has a textblock and a button.
The Button IsEnabled is bound to a Converter with three values from the ViewModel (properties A-C) and one from the datagrid.ItemSource (Id).
<Button Tag="{Binding Id}"
IsEnabled="{multibinding:MultiBinding Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged,
Source1={Binding Path=DataContext.PropertyA, ElementName=LayoutRoot},
Source2={Binding Path=DataContext.PropertyB, ElementName=LayoutRoot},
Source3={Binding Id},
Source4={Binding Path=DataContext.PropertyC, ElementName=LayoutRoot},
Converter={StaticResource myConverter}}">
The Button Click event is bound to a command on my viewModel.
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding Path=DataContext.ClickCommand, ElementName=LayoutRoot}"
CommandParameter="{Binding Id}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
Firing the OnPropertyChanged event in viewModel
public void OnClickCommand(int Id)
{OnPropertyChanged("PropertyA");}
I've actually just put a hack in place to refresh the whole control which will reinitialise and re-fire the converter but any help to solve this would be much appreciated.

Attach Prism Command to Grid?

Is it possible to create a command behavior using Prism's CommandBehaviorBase class for Silverlight's grid? I know that it is only intended for actual controls, so I was wondering if anyone might know if a workaround. I would like to create an attachable mouse over behavior for a grid, that executes a specific command, and ideally would like to use Prism for this approach, just can't seem to use CommandBehaviorBase for a Grid.
Thanks.
The arguably easier way to achieve this is to use Triggers. Doesn't require you to write any code, all you have to do is this:
<Grid>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseEnter">
<si:InvokeDataCommand Command="{Binding DoSomethingCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
...
</Grid>
Here the DoSomethingCommand (defined in a ViewModel) will trigger when MouseEnter event is fired on the Grid.

Categories