I'm learning MVVM through a project and I got stuck on something simple.
I have a Button that updates a ListView. I have a command in the ViewModel that make the right things but I want to select the new row and get the focus on a TextBox after I click the Button.
The question is: How do I update my UI after executing a command?
If I need to change my windows Title when an operation have been made, I use a property on the ViewModel that is binded to the Window's title and it's changed when I need it but, I don't know how to get focus on a control when a command has been executed.
Thank you.
To select the new row, add a new property to your ViewModel ("SelectedItem" for instance), and bind the ListView's SelectedItem property to it :
<ListView ItemsSource="{Binding Items}" SelectedItem="{Binding SelectedItem}">...
In the ViewModel, you just have to assign the new item to the SelectedItem property
To focus the TextBox, Mike's idea seems a good one
You could make an attached behavior. I'd suggest using the new Blend behavior framework, ie TriggerAction that contained this custom logic.
For your attached behavior you put on the button, give it a DP for an ICommand and maybe a DP of a ListView type.
On the "protected override void Invoke(object parameter)" of your TriggerAction, execute your ICommand, then you have reference to your ListView. Here you can do your custom code on it, like setting focus.
Your XAML may look something like this:
<Button>
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<Behaviors:CustomBehavior Command="CommandName" ListView="{Binding ElementName=myListView}" />
</i:EventTrigger>
</i:Interaction.Triggers>
<Button/>
I suggest looking at Mike Brown's ExecuteCommandAction behavior (download here), it's about almost 1/2 of what you need.
What about setting focus to the control in the code behind: textBox.Focus()
I consider everything you mention in your question to be GUI logic so I would add a Click event to the button to handle stuff that needs to happend in the GUI.
Hope this helps.
I think you need to use the Mediator pattern. Please see this:
Josh Smith's Mediator Prototype for WPF Apps
This is generally used in communicating with the View from the View-Model. Hope this helps.
In your case you need some way that the ViewModel notifies the View that it should set the focus on a specific control.
This could be done with an IView interface. The view implements this interface and the ViewModel can call a method of the View over this interface. This way you have still the View and ViewModel decoupled of each other.
How this can be done is shown here:
WPF Application Framework (WAF)
http://waf.codeplex.com
Related
i've got a textbox which text is binded to a listview selecteditem as follows:
<TextBox x:Name="txtAdditional" Width="300" Text="{Binding ElementName=lstPersons, Path=SelectedItem.Additional, Mode=OneWay}" />
Now i like to implement a mechanism to add new items to the listview using this textbox to get the actual data. So i would like to bind the text of the textbox to a property of the viewmodel so it can be processed by a command.
So it the textboxes text has to be binded to the listviews selecteditem and additionally to a property of my viewmodel.
I've searched around and found some approaches but i can't help to think that there should be some simpler mechanism to archive this goal.
What I found by now:
Using MultiBindung with some kind of ValueConverter? So it seems to me that this is primary for displaying and not for updating a viewmodels property.
The use of some selfdefined custom control?
The use of an BindingProxy with in- and out-dependencyproperties like in Impossible WPF Part 1: Binding Properties?
Is there another, simpler solution to this or would i have to use one of those above?
And if one should use one of those approaches, which one whould you choose?
I can't help but thinking that this issue hasn't been given some thoughts already, using an mvvm pattern?! ;-)
yes thanks to the hint from BionicCode.
We, or better I should have to think the MVVM concept out. Of course no - or at least as little code behind as possible.
I added the property "selectedPerson" to my viewmodel and bound the SelectedItem of the listview to this property. So the object related properties were at hand directly through the "selected" object in my viewmodel and there was no need anymore to access the textbox content at all.
Thanks to BionicCode for the hint!
I have a accustom control bound to a model class. So if any change in UI for textbox it updates ViewModel.model instance. but it doesnot work the other way. What is the necessary thing I need to look for? or troubleshoot steps pls.
Thanks.
You mean the value is displayed in the Textbox but a new typed value isn't?
If so you need to set two way binding on the Textbox binding:
<Textbox Text={Binding myTextProperty, Mode="TwoWay", UpdateSourceTrigger="ProprtyChanged"/>
This will enable both read & write functionality to your binding.
As #Ganesh says, you also need to make sure you're implementing the INotifyPropertyChanged interface in your ViewModel.
I have situation like this, I have 2 WPF forms developed using MVVM Pattern ..2nd form will be opened from first(form1 will be in backend till form2 is closed) and closing the second makes the first form active.
Now I want to make a textbox on form1 with default focus set on it. I was able to do it with FocusManager and its working fine but the same is not working fine when Im getting into form1 from form2. Also during this time I have to set the focus on the default textbox and also I need to select all the text present on it. I am unable to understand how to do this with viewmodel.
Any suggestions will be of great help for me.
Regards,
Krishna
You can focus a particular UI element using the FocusManager.FocusedElement Attached Property:
<Grid FocusManager.FocusedElement="{Binding ElementName=SomeTextBox}">
<TextBox Name="SomeTextBox" Text="{Binding SomeProperty}" />
</Grid>
This should select the TextBox each time the view/UserControl is loaded.
As for how to select text from the view model... the solution would be the same to handle any event when using MVVM. Wrap it in an Attached Property. Please beware that it is not appropriate to handle all events in the view model, as it should not really have any knowledge of purely UI events. However, the choice is yours.
To 'wrap', or handle any event in an Attached Property, you basically declare a class that extends the DependencyObject class and define one or more static properties. Rather than go over the whole story once again, I'd prefer to direct you to my answer to the What's the best way to pass event to ViewModel? question on Stack Overflow, which provides further links and a full code example.
For background information on Attached Properties, please see the Attached Properties Overview page on MSDN.
I am trying to take the currently selected objects (rows) in a DataGrid control and send them directly to the View Model (MVVM pattern) without any code in the XAML code behind, using ICommand.
I have done this with a Button since ButtonBase implements the Command property - the DataGrid does not. It appears that using Commands between the View and the View Model when using buttons is the convention, but what about other controls?
Is there a way to take the currently selected items and send this in a Command to the View Model?
Here's an article on the subject. It's about Silverlight, but the guidance should be useful for WPF as well. Basically it says to use something like EventToCommand (from MVVMLight Toolkit) to translate the SelectionChanged event into an ICommand.
I like to use the code found here. It is some AttachedProperties which let you hook up Commands to just about any Event
<DataGrid
local:CommandBehavior.Event="MouseDown"
local:CommandBehavior.Command="{Binding SomeCommand}"
local:CommandBehavior.CommandParameter="{Binding SelectedItem}"/>
We're using Views and ViewModels in this project, and as a result we're trying to have as little in the code-behind for the View as possible.
I'm trying to tie the MouseDoubleClick event for a WPFToolkit DataGrid to the same code that a Button in the same view already is using.
The Button is declared as the following:
<Button Content="Select" cmd:ButtonBaseExtensions.Command="{Binding CommandViewEmployer}"/>
which means it runs the CommandViewEmployer Property in the ViewModel. How do I get the Grid MouseDoubleClick to run the same property? I've tried adding MouseDoubleClick="{Binding CommandViewEmployer}", which errors.
I'm trying to get this in as little code-behind as possible, none preferably.
You can use something like Marlon Grech's attached command behaviors.