Initiating UserControl via MVVM in WPF / focus issue - wpf

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.

Related

Catching right mouse click on user control level

<UserControl>
<Grid>
<!-- multiple controls here -->
</Grid>
</UserControl>
As the above example says, there are multiple MS / 3rd party controls hosted on UserControl. I need to catch mouse right click over the UserControl (or any of its child controls). It seems that PreviewMouseRightButtonUp event is not fired when clicked on some of the 3rd party controls inside the UserControl. As per documentation, PreviewMouseRightButtonUp is not a tunneling event, but a direct event, so it is possible that some 3d party controls do not notify the subscribers about this event.
I have also tried to add handler to this event, but still no result
AddHandler(UserControl.PreviewMouseRightButtonDownEvent, new RoutedEventHandler(GetHandledToo), true);
AddHandler(UserControl.PreviewMouseRightButtonUpEvent, new RoutedEventHandler(GetHandledToo), true);
AddHandler(UserControl.MouseRightButtonDownEvent, new RoutedEventHandler(GetHandledToo), true);
AddHandler(UserControl.MouseRightButtonUpEvent, new RoutedEventHandler(GetHandledToo), true);
So, is there a way to always catch the right mouse button event on the user control level, no matter if it is being marked as handled or not?
Edit: I have found where the problem lies. The problem lies in the ContentControl which has not yet evaluated its content. Example:
<ContentControl x:Name="chart" Content="{Binding DiagramScreen}" />
ContentControl recolves its structure through DataTemplate. If DiagramScreen is NULL, the ContentControl's content is not yet created. This means that the space that this ContentControl occupies in UserControl is not responding to Mouse events. How Can I make ContentControl respond to mouse events, even if its content is NULL?
I think if it is handled you can't get it further for bubbling event. A workaround is to pass your host object to your user control. After that, you can call whatever method you want from your host object. It's ugly but I think it will work

WPF MVVM Default Focus on Textbox and selectAll

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.

Bind border style to current user control

I`m developing a wizard application which has a side menu with 5 borders and a content control that contain application screens (user controls).
The borders styles are suppose to give to user an indication where he is at the wizard steps.
I wrote 2 border styles - the first one is the defult style which applied on all borders by default.
The second one (isFoucusedStyle) need to be applied by the border that suitable to the current screen.
For example when the wizard is showing the first screen: first border need to use the isFoucusedStyle and the others need to use defult style. When the user continues to next screen, the first border need get back to default style and the second border now will apply isFoucusedStyle.
I create the pages instances via xaml at the mainWindow under resources at the next way:
xmlns:view="clr-namespace:App.View"
xmlns:ViewModel="clr-namespace:App.ViewModel"
<Window.Resources>
<DataTemplate DataType="{x:Type ViewModel:OpeningViewModel}">
<view:OpeningView/>
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModel:PersonalDataViewModel}">
<view:PersonalDataView/>
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModel:BusinessDataViewModel}">
<view:BusinessDataView/>
</DataTemplate>
<DataTemplate DataType="{x:Type ViewModel:BusinessDataViewModel}">
<view:BusinessDataView/>
</DataTemplate>
I also have a property - CurrentPage which binded to ContentControl - when the user clicks "next page button" CurrentPage updates and the ContentControl switch UserControl.
There is no any binding between the borders to User Controls, in my current state the borders are just visual graphics without any features.
How can i implement it?
Thanks
I took the "isFoucusedStyle" and config it to baseOn defultstyle.
I added triger to isFoucusedStyle which turns on when Border.Focusable is true.
I Created a converter which has access to current page number.
At every border I bounded focusable property to the converter and sent it "converter parameter" with the suitible page number (page number which represented by current border)
The converter is checking for equility between currentPageNumber to converterParameter and returns boolean result.
The result is turning on (or not) the trigger and set the needed border style.
Thanks anyway.
Firstly I would strongly suggest you base your wizard on the NavigationWindow (or containing a NavigationFrame), this will give you all your back and forwards navigation for free, and if you want you can always re-style your NavigationWindow to match a more wizard like interface (see WPF Wizards). NavigationWindow/Frame also supply you with Navigate() methods that handle the transition between pages.
In order to handle the navigation links (your five side menu items) I bind each link to a View level ICommand which tests to see if we need are already on the correct page in CanExecute. Setting ths borders is then just a case of {Binding CanExecute, Converter={BoolToColorConverter}}.
In your case, you can simply do the same thing. Setup your command to check if we have the right CurrentPage, and Bind as above using a Converter.

TemplateBinding DataContext in silverlight CustomControl

I have a rather interesting case with ComboBox control - CustomComboBox;
In the style of this ComboBox, Popup contains one custom control that requests a DataContext;
<ctrl:CustomGrid DataContext="{TemplateBinding DataContext}" GridName="{Binding Preferences.CurrentGridName}"/>
The idea:
to use this control several times on one page
to use it in a masterpage container
the masterpage control needs to have different DataContexts regarding the Page it is on
The logic:
In the overriden OnApplyTemplate I am getting the grid and connecting few eventhandlers
The problem:
The masterpage control is triggering OnApplyTemplate only once
The first appearance of the CustomComboBox is as expected.
However, every next apearance is with same DataContext, even when changing the datacontext of the CustomComboBox
These changes don't reach to change my CustomGrid DataContext
I am sure that something on the bindings or the presentation logic is bad...
Please throw some thoughts on, I would appreciate a hint here
Thanks
OnApplyTemplate is called when a ControlTemplate is applied to the control that overrides the method (neither its parent, nor children). If OnApplyTemplate is entered once, the overriding control must also be created once. I mean you simply have a single masterpage instance. This shouldn't be unexpected.
Speaking about Popups and DataContext, there often are issues with bindings from a Popup to outside it. So, I would rather write some code-behind to deliver correct context to Popups, instead of relying on Bindings. There sure is a problem of DataContextChanged event absence prior to SL5. To workaround this one, you should define your custom DependencyProperty on your CustomComboBox, bind it to the CustomComboBox's context and assign its value to the Popup in the PropertyChangedCallback.

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.

Resources