WPF MVVM Default Focus on Textbox and selectAll - wpf

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.

Related

WPF Custom control with textbox doesnot update from viewmodel changes

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.

How to clear a TextBox in a User Control in WPF C#?

I have a user control that has a textbox in it, and i am using a clear button on my main form to clear information from the entire main window. i would like to clear the textbox in the user control once the clear button is clicked as well. i havent found an easy way to do this. i have tried referencing the control's name in c# followed by a "." however the name of the text box does not show up. any help would be appreciated!
WPF declares controls in a UserControl as private. To make your TextBox public you declare it with a FieldModifier as in:
<TextBox x:FieldModifier="Public" />
where x is the xaml namespace xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml". However the recommended way of clearing a TextBox is to bind it to a property and then clear the property.
You should not try to directly access controls within a UserControl from external classes or code. The simple mechanism would be to add a Clear() method to the UserControl which clears all relevant controls and information inside the UserControl.
The textbox could be bound to the DataContext of the UserControl. So a way of clearing it might be setting the property that is bound to the Text property of the TextBox to an empty string.

Setting a property on the ViewModel from the View in WPF

I have a dependency property on my ViewModel which is the DataContext for my View. The ViewModel has no reference to the View. The property on the ViewModel is going to reference a control on the view, but I need to be able to set this property in XAML.
How is this possible? One thought I had was to develop a custom control which has a Property property and a Value property, so you could do something like this in the View to set the property on the ViewModel:
<PropertySetter Property="{Binding MyViewModelDependencyProperty}" Value="{Binding ElementName=aControlOnMyView" />
Before I went down this route, I wanted to check if there was any other approach I could take?
Thanks for the detailed reply Ray, but if I give you a bit more detail about the problem I'm trying to solve, you might get a better idea of why I mentioned the approach I did.
Basically, what I'm trying to do is set the focus to a textbox when the user hits a button. I've written an attached property which you can attach to the Button control, specify what the trigger event is (in this case the 'Click' event), and then what control to focus on. This works really nicely, and keeps everything in XAML.
However, I now have a use case where the focus should be set to an arbitrary text box from the click event on a button which is part of a toolbar. This toolbar is itself a user control which is sitting inside another user control, which is inside another user control! This toolbar needs to be reusable across various different forms, and each time, the control to set focus on after you click the button will be different per form.
That's why I had the idea of making the focus control (i.e. a textbox) a property on the view model itself (on my ViewModel base to be precise), and have the ViewModel base code (which the toolbar is bound to), set the focus to the control when the button is clicked (and the e.g. Add/Edit method is called on the ViewModel base).
In unit test land, the control to focus on property will be null, so it's .Focus() method just won't be called. So I can't see an issue there. My problem is then how you set the focus control property from XAML, which is why I had the PropertySetter idea.
I don't like the fact that the ViewModel has any reference to controls sitting on the view, but I can't see another way to achieve what I need. What if the logic that dictates whether to set focus to the control is quite complex? This would sit in the ViewModel surely? Therefore, is there any harm in the ViewModel having this UIElement property? It still knows nothing about the specific View it is bound to, it just knows that there is a control which it needs to set focus to when some action happens on the ViewModel.
My first reaction (and it's a strong one) is so say "Don't do that!" By giving your view model a reference to a part of your UI you are breaking the encapsulation that makes view models so powerful and useful.
For example, what if you want to unit test your view model or serialize it to disk? In each case the piece of your UI will not be present, because there will be no view at all. Your tests will miss coverage and your reconstitution will be incomplete.
If your view model actually needs references to UI objects and there is no better way to architect it, the best solution is to have the view model itself construct those controls it requires a reference to. Then your view can incorporate that control as the Content of a ContentPresenter via binding and provide a Style to configure the control, including a ControlTemplate to provide its content. Thusly:
public class MyViewModel
{
public ListBox SpecialControl { get; set; }
public MyViewModel()
{
SpecialControl = new ListBox();
}
}
and
<DataTemplate TargetType="{x:Type local:MyViewModel}">
<DataTemplate.Resources>
<Style TargetType="ListBox" ... />
</DataTemplate.Resources>
...
<ContentPresenter Content="{Binding SpecialControl}" />
</DataTemplate>
Other possibilities are:
Have the view model actually derive from the Control class, then override OnApplyTemplate() and use GetTemplateChild to find a template item whose name starts with "PART_"
Implement an attached property that takes a property name, finds that property in the DataContext, and sets it to the DependencyObject to which the property is attached.
Implement your PropertySetter idea
My option #2 would look like this:
<DataTemplate TargetType="{x:Type MyViewModel}">
...
<TextBox local:PropertyHelper.SetViewModelToThis="SpecialControl" />
...
</DataTemplate>
The code in the SetViewModelToThis PropertyChangedCallback would get the view model from the DataContext, reflect on it to find the "SpecialControl" property, then set it to the TextBox. Note that the implementation of SetViewModelToThis must take into account the possiblity that DataContext is not set right away, and that it maybe changed requiring the old setting to be removed and a new one made.
First of all, the DataContext of the control should be the ViewModel object and not a property of it. Second, when you TwoWay bind a property of ViewModel to your control, changes in the control's value will update (in your case, 'set') the value of ViewModel's property.

Initiating UserControl via MVVM in WPF / focus issue

I have a few usercontrols loaded into a tabcontrol via MVVM in WPF.
Within the XAML for the usercontrol I am setting focus to a textbox using the FocusManager, however this appears to only work when the first instance of the usercontrol is created.
Just to test I added a loaded event handler to the usercontrol - this is only called on the first instance.
I'm using data templates for the user controls as follows:
<DataTemplate DataType="{x:Type local:UserTypeViewModel}">
<local:UserTypeView />
</DataTemplate>
The textbox is focused as follows:
FocusManager.FocusedElement="{Binding ElementName=txtName}"
Additionally I'm using a global event handler (for the textbox GotFocus event) which selects all the text using a dispatcher.
If anyone has any tips on how to achieve focus with every usercontrol I'd be very grateful.
Thanks, Ben.
Remember that a visual element can only receive focus, if:
It is visible (in a TabControl only one tabitem can be visible at a time
IsFocusable must be set to true (is default false for UserControls)
It has finished loading (as you write - do it in the Loaded event))
I think the first reason is why it only works for the first element.
As for how to achieve it for all controls - you can use a style with an EventSetter for the Loaded event. You need to make a style per type of control though to avoid having to set it for each control.

MVVM What is the way of updating a UI after a command?

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

Resources