I have data coming from the service that has 7 columns. I can show them all in the grid view but I like to know how to show 2 of those columns in another control may be textblock.
So when someone clicks on the row, the second control will be updated with information in the other two columns.
I tried to use this in my MVVM
</ListView.View>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<i:InvokeCommandAction Command="{Binding OnRowClickCommand}" CommandParameter="{Binding}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListView>
Has anyone tried to do this before ? Any examples would be great help.
Turns out it was very simple.. Here it is if anyone else wants to know. Did not need event handler etc.
<TextBlock Text="{Binding ElementName=ListViewName,Path=SelectedItem.Column}"/>
However I am not sure currently how I can conditionally show a label for this information..
Related
I wanted to handle MainWindow's Closing event in one of my ViewModel. This ViewModel belongs to a View which is displayed on top of the MainWindow. I wanted to save values of some properties present in that ViewModel while/before closing of the application.
I am using MvvmCross to implement MVVM pattern. So I tried overriding ViewDisappearing, ViewDisappeared and ViewDestroy methods, but they are only getting called when View get switched, but not when application/window closes.
While searching for this requirement, I could only find this answer: https://social.msdn.microsoft.com/Forums/vstudio/en-US/477e7e74-ccbf-4498-8ab9-ca2f3b836597/how-to-know-when-a-wpf-usercontrol-is-closing?forum=wpf , which is close to my requirement, but needs to be implemented in code-behind.
Can anyone please help me in achieving this in MVVM/MvvmCross in WPF?
I had some experience to implement events by MVVM maybe it can help you.
As I know there is a package on Microsoft.Xaml.Behaviors.Wpf that will help to get the events and execute a command
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<i:InvokeCommandAction Command="{Binding ClosingWindow}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
and if you want to execute a command in other view models you can use a static command
xmlns:local="clr-namespace:App.Views.Windows"
xmlns:i="http://schemas.microsoft.com/xaml/behaviors"
<i:Interaction.Triggers>
<i:EventTrigger EventName="Closing">
<i:InvokeCommandAction Command="{x:static local:ViewModel.ClosingWindow}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
I am having some trouble with an editable ComboBox and the updating of a binding. Currently I have a ComboBox where its UpdateSourceTrigger=LostFocus this is because I need to wait for the user to finish inputting somthing before I decide if the value is a new value (and thus create a new one).
Unfortunately, I have another feature which requires the binding to update when the value has changed aswell. Aka, LostFocus is no good to me in this case. As selecting a new value within the ComboBox it doesn't cause the LostFocus to fire (obviously). So I need to find a way to force update the binding.
I have looked into the SelectionChanged and forcing the update on the binding:
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding ParentConversation.ViewModel.ComboSelectionChanged}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type controls:StoryForgeComboBox}}}"/>
</i:EventTrigger>
And updating the binding in code behind like so:
be = BindingOperations.GetBindingExpression(ele, ComboBox.TextProperty);
if (be != null)
{
be.UpdateSource();
}
Unfortunately I CANNOT update the binding at this point as the value has yet to change. See this stackoverflow topic: ComboBox- SelectionChanged event has old value, not new value
There is a trick where you can possibly use the DropDownClosed event and then update the binding, this works but does not work if you use the Up/Down arrow keys which never opens the ComboBox. Also hooking into KeyUp and KeyDown is too early. The binding cant be updated yet.
So my question is, when is a good time to say "Hey Mr Combo Box, You can update your bindings now".
Cheers.
You can change the SelectionChanged event trigger to LostFocus:
<ComboBox
IsEditable="True"
ItemsSource="{Binding Items}"
SelectedItem="{Binding SelectedItem}"
Text="{Binding Text, UpdateSourceTrigger=PropertyChanged}">
<i:Interaction.Triggers>
<i:EventTrigger
EventName="LostFocus">
<i:InvokeCommandAction
Command="{Binding Command}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</ComboBox>
When the user types, Text is updated.
When the user types and the ComboBox finds a match in the Items, SelectedItem is changed.
When the user types, the ComboBox does not find a match and a item was previously selected, SelectedItem is set to null.
When the user selects an item, both SelectedItem and Text are updated.
When the user leaves the ComboBox (losing focus), Command is triggered.
When the user has typed text and opens the drop down list, Command is triggered.
EDIT: strangely enough Command is also triggered when it receives focus.
Is this the behavior you want?
I have another question with windows phone 7 dev. I'm creating listbox with items and one textblock, which is something like link to another page. Each link will have another "page" variable value.
<TextBlock Tap="TextBlock_Tap" Foreground="#FF40AA2F" Text="View details">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseLeftButtonDown">
<ec:NavigateToPageAction TargetPage="/details.xaml?page={Binding Index}" />
</i:EventTrigger>
</i:Interaction.Triggers>
</TextBlock>
But it doesn't work with current value in targetpage, because Visual Studio taking it like normal string. How can I embed this binding in page variable? Thank you
Try using StringFormat:
<ec:NavigateToPageAction TargetPage="{Binding Path=Index, StringFormat='/details.xaml?page={0}'}" />
Do the navigation, not on a trigger but in the code behind of the MouseLeftButtonDown event of the Text Block and extract the target page from the current selection of the listbox.
Let's say I currently have an ItemsControl whose DataTemplate is a bunch of buttons. I'm wiring up these buttons' click events, but how am I to know which button was clicked? Should I not use a ItemsControl?
I'm trying to have no code-behind, but being pragmatic may be necessary.
<ItemsControl>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Button Margin="10">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<GalaSoft_MvvmLight_Command:EventToCommand Command="{Binding ItemsControlButtonClicked, Mode=OneWay}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
If you want to know what Item was clicked, then pass {Binding } as the CommandParameter and it will pass the selected object to your Command
If you want to know what Button was clicked, I would do that in the code-behind since ViewModels do not need to know anything about the UI, and that includes buttons.
Also since your control is a Button, you should use the Command property instead of a Click trigger.
<Button Command="{Binding ItemsControlButtonClicked}" />
You can send parameters along with the command and based on these parameters you can find out which button was clicked
In my project I also use the MVVM Light I has an dropdown with collection of items, and a button which user press and action depend on selected item from drop down
you should create a Relay command with parameter look at the example from my code
public RelayCommand<Project> StartTimer { get; private set; }//declare command
StartTimer = new RelayCommand<Project>(OnStartTimer);
private void OnStartTimer(Project project)
{
if (project != null)
{
currentProject = project;
if (!timer.IsTimerStopped)
{
timer.StopTimer();
}
else
{
Caption = "Stop";
timer.StartTimer();
}
}
on the view I bind the drop down with collection of class Project
and for button command parameter I bind the selected item form drop down
look at the code
<ComboBox Name="projectcomboBox" ItemsSource="{Binding Path=Projects}" IsSynchronizedWithCurrentItem="True" DisplayMemberPath="FullName"
SelectedValuePath="Name" SelectedIndex="0" >
</ComboBox>
<Button Name="timerButton" Content="{Binding Path=Caption}" Command="{Binding Path=StartTimer}"
CommandParameter="{Binding ElementName=projectcomboBox, Path=SelectedItem}" ></Button>
pay attention to Command and CommandParameter binding
also you can use this approache not only for drop down
Well, you can use the Sender.DataContext which is the actual data.
Create command properties in your view model class (using Josh Smith's RelayCommand pattern is the simplest way to do this) and bind each button's Command to the appropriate one. Not only is this straightforward to do and simple to maintain, it also gives you an easy way of implementing the enable/disable behavior when you need to.
I am currently transforming a medium size WPF project to MVVM and I ran into a problem that I wasn't able to solve, yet. Maybe you could help me out?
The target framework is .NET 3.5.1.
I have a list view that gets its items from the underlying view model. That view model is exposing a command to remove the selected items from the list view. Therefore the command parameter is bound to the SelectedItems property of the list view.
<ListView ItemsSource="{Binding MyItems}"
x:Name="MyListView"
SelectionMode="Extended">
</ListView>
<Button x:Name="MyRemoveButton"
Content="Remove item"
Command="{Binding RemoveItemCommand}"
CommandParameter="{Binding ElementName=MyListView, Path=SelectedItems}">
My intention is to execute this command not only when pressing a button, but also when the KeyUp event is fired on the list view and the pressed key is "delete".
I was close to finding the solution when I stumbled upon interaction triggers in this example:
http://joyfulwpf.blogspot.com/2009/05/mvvm-invoking-command-on-attached-event.html?showComment=1250325648481#c3867495357686026904
Now the problem with this demo is that the command parameter is the pressed key, but in my case I need the command parameter to be the SelectedItems property and I need the command to execute only on a specific key.
Is there any way to do this without much overhead and in the MVVM way?
Something like this would be awesome:
<i:Interaction.Triggers>
<i:EventTrigger EventName="KeyUp">
<local:CommandAction Command="{Binding RemoveItemCommand}"
CommandParameter={Binding ElementName=MyListView, Path=SelectedItems}
EventArgument="Key.Delete"/>
</i:EventTrigger>
</i:Interaction.Triggers>
To do it in the MVVM way you need to bind "SelectedItems" property of the ListView to your ViewModel, so you could use it from your commands and wouldn't need to pass it via CommandParameter.
How strict is your separation requirement? If you don't have designers using Blend, then put a call to a ViewModel method into the KeyUp or PreviewKeyUp event handler in your code-behind.