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.
Related
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>
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.
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
I am having trouble and don't know what to pass as command parameter.
<triggers:Interactions.Triggers>
<triggers:EventTrigger EventName="ItemClick">
<triggers:InvokeCommandAction Command="{Binding MenuItemClick}" CommandParameter=""/>
</triggers:EventTrigger>
</triggers:Interactions.Triggers>
This is inside gridview declaration. I want to recieve gridview clicked item in binded delegate as parameter.
You can set the PassEventArgsToCommand property of the InvokeCommandAction to true which will allow to pass ItemClickEventArgs pp to your command.
<triggers:InvokeCommandAction
Command="{Binding MenuItemClick}" PassEventArgsToCommand="True"/>
or see this article which provides more reliable solution from view point of better design.
I have a list view that is populated from a mysql table, I want to be able to double click on a item in the listview and bring up a new window with more information. How do I pass the first column value to the new window (this is the id of the item)? This way I can make another query to get the rest of the info about the item.
Was having a similar issue with a ListBox wanting to open a window (Different View) with the SelectedItem as the context (in my case, so I can edit it).
The three options I've found are:
1. Code Behind
2. Using Attached Behaviors
3. Using Blend's i:Interaction and EventToCommand using MVVM-Light.
I went with the 3rd option, and it looks something along these lines:
<ListBox x:Name="You_Need_This_Name"
ItemsSource="{Binding Your_Collection_Name_Here}"
SelectedItem="{Binding Your_Property_Name_Here, UpdateSourceTrigger=PropertyChanged}"
... rest of your needed stuff here ...
>
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseDoubleClick">
<Command:EventToCommand Command="{Binding Your_Command_Name_Here}"
CommandParameter="{Binding ElementName=You_Need_This_Name,Path=SelectedItem}" />
</i:EventTrigger>
</i:Interaction.Triggers>
That's about it ... when you double click on the item you want, your method on the ViewModel will be called with the SelectedItem as parameter, and you can do whatever you want there :)
What is meant with MVVM is that you will have for example a ViewModel containing a property SelectedThing bound to the SelectedItem of the listview and a command that gets executed using EventCommand on the MouseDoubleClick event of the View which will execute in the end the operation you want on the SelectedThing which could be also passed in as parameter to the command also by binding.