Blogginlägg

Set focus via XAML

Av Cecilia Wirén | Blogg | 17 maj 2016

Att få fokus på en grafisk kontroll görs genom att anropa Focus() funktionen på denna kontroll men att göra detta rimmar illa med MVVM mönstret speciellt om det är något från vymodellen som skall bestämma om det skall vara focus eller inte. Detta problem löser vi enklast med en så kallade extension, då kan även få till databinding.
En extension skrivs som en egen klass med set och get funktion för värdet samt en dependency property där vi fångar upp när värdet ändras och har då möjlighet att anropa Focus().
public static class FocusExtension
{
public static bool GetFocused(DependencyObject o)
{
return (bool)o.GetValue(FocusedProperty);
}

public static void SetFocused(DependencyObject o,
bool value)
{
o.SetValue(FocusedProperty, value);
}

public static readonly DependencyProperty FocusedProperty =
DependencyProperty.RegisterAttached("Focused",
typeof(bool), typeof(FocusExtension),
new UIPropertyMetadata(false, OnValueChanged));

private static void OnValueChanged(DependencyObject d,
DependencyPropertyChangedEventArgs e)
{
var uie = (UIElement) d;
if ((bool)e.NewValue)
{
uie.Focus();
}
}
}
I denna extension finns det inget vi ska/kan göra vid ett falskt värde, det finns ingen UnFocused() funktion utan de grafiska elementen blir av med sin fokus genom att någon annan tar den.
För att sedan använda den på te.x. en TextBox med en binding till vymodellen (förutsätter att du har propertyn Focus i din VM och helst också med ett OnPropertyChange event i dess setter):
<TextBox uiEx:FocusExtension.Focused="{Binding Focused}"/>
Eller med ett direkt värde:
uiEx:FocusExtension.Focused="True"
Du kan också behöva inkludera namespacet om du inte redan har gjort det (eller fått hjälp av verktyg). Det ser ut såhär:
xmlns:uiEx="clr-namespace:CSharpSoftware.UIExtensions"
Om du har följande namespace runt din extension klass:
namespace CSharpSoftware.UIExtensions
{
public static class FocusExtension
{
Till inlägget