I needed to be able to set the Focus of a control, using MVVM. This means of course, that we can’t interact directly with the View, but instead must rely on Binding.
I found a very helpful post by Khalid Rafique which allows exactly this;
http://codenicely.blogspot.co.uk/2012/01/how-to-set-textbox-focus-in-silverlight.html
By making use of attached Interactivity Behaviours, we can Bind an IsFocused Property, allowing the focus of the selected control to be set..Very handy indeed.
The VB.net code is shown below;
Behaviour Class:
Imports System.Windows.Interactivity
Namespace Behaviours
Public Class clsFocusBehavior
Inherits Behavior(Of Control)
#Region "Properties"
''' <summary>
''' The IsFocused Property, which is a backing for the IsFocusedProperty Dependancy Property
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property IsFocused() As Boolean
Get
Return CBool(GetValue(IsFocusedProperty))
End Get
Set(value As Boolean)
SetValue(IsFocusedProperty, value)
End Set
End Property
''' <summary>
''' The Has Initial Focus Property, which is a backing for the HasInitialFocusProperty Dependancy Property
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property HasInitialFocus() As Boolean
Get
Return CBool(GetValue(HasInitialFocusProperty))
End Get
Set(value As Boolean)
SetValue(HasInitialFocusProperty, value)
End Set
End Property
#End Region
#Region "Dependancy Properties"
''' <summary>
''' Expose an IsFocused Dependancy Property to allow Binding
''' </summary>
''' <remarks></remarks>
Public Shared ReadOnly IsFocusedProperty As DependencyProperty = DependencyProperty.Register("IsFocused", GetType(Boolean), GetType(clsFocusBehavior), New PropertyMetadata(False, Sub(d, e)
If CBool(e.NewValue) Then
DirectCast(d, clsFocusBehavior).AssociatedObject.Focus()
End If
End Sub))
''' <summary>
''' Expose a HasInitialFocus Property, which allows Binaind dicating if the Control should be focuses Initially
''' </summary>
''' <remarks></remarks>
Public Shared ReadOnly HasInitialFocusProperty As DependencyProperty = DependencyProperty.Register("HasInitialFocus", GetType(Boolean), GetType(clsFocusBehavior), New PropertyMetadata(False, Nothing))
#End Region
#Region "Helper Subs"
''' <summary>
''' Override the OnAttached Sub... Add Event Handlers
''' </summary>
''' <remarks></remarks>
Protected Overrides Sub OnAttached()
AddHandler AssociatedObject.GotFocus, Function(sender, args) InlineAssignHelper(IsFocused, True)
AddHandler AssociatedObject.LostFocus, Function(sender, a) InlineAssignHelper(IsFocused, False)
AddHandler AssociatedObject.Loaded, Sub(o, a)
If HasInitialFocus OrElse IsFocused Then
AssociatedObject.Focus()
End If
End Sub
MyBase.OnAttached()
End Sub
''' <summary>
''' Used to simplify assigning the Target Vaues of Control Events
''' </summary>
''' <typeparam name="T"></typeparam>
''' <param name="target"></param>
''' <param name="value"></param>
''' <returns></returns>
''' <remarks></remarks>
Private Shared Function InlineAssignHelper(Of T)(ByRef target As T, value As T) As T
target = value
Return value
End Function
#End Region
End Class
End Namespace
XAML to add to View Header Namepaces:
xmlns:Behaviors="clr-namespace:CriticalPath_WPF_MVVM_EF.Behaviours"
XAML to add to control:
<i:Interaction.Behaviors>
<Behaviors:clsFocusBehavior HasInitialFocus="False" IsFocused="{Binding DataContext.OrderNumberFocus, Mode=TwoWay, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}"/>
</i:Interaction.Behaviors>
Code to add to ViewModel:
Private _OrderNumberFocus As Boolean
''' <summary>
''' The Order Number Focus
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property OrderNumberFocus As Boolean
Get
Return _OrderNumberFocus
End Get
Set(value As Boolean)
_OrderNumberFocus = value
OnPropertyChanged("OrderNumberFocus")
End Set
End Property
Set the Focus using;
OrderNumberFocus = True
No comments:
Post a Comment