I have a requirement to focus on a specific textbox when a new view is loaded.
The solution was to add this line of code to the OnLoaded event for the view:
Without a BusyIndicator
present in the view, the common solution to solve the focus problem is to add the code
Dispatcher.BeginInvoke(() => { ControlToFocusOn.Focus(); });
to the Loaded
event of the view. This actually works even with the BusyIndicator
present; however, the BusyIndicator
immediately takes focus away from the rest of the Silverlight controls. The solution is to invoke the Focus()
method of the control after the BusyIndicator
is not busy.
I was able to solve it by making a control like this:
public class EnhancedBusyIndicator : BusyIndicator
{
public EnhancedBusyIndicator()
{
Loaded += new RoutedEventHandler(EnhancedBusyIndicator_Loaded);
}
void EnhancedBusyIndicator_Loaded(object sender, RoutedEventArgs e)
{
AllowedToFocus = true;
}
private readonly DependencyProperty AllowedToFocusProperty = DependencyProperty.Register("AllowedToFocus", typeof(bool), typeof(EnhancedBusyIndicator), new PropertyMetadata(true));
public bool AllowedToFocus
{
get { return (bool)GetValue(AllowedToFocusProperty); }
set { SetValue(AllowedToFocusProperty, value); }
}
public readonly DependencyProperty ControlToFocusOnProperty = DependencyProperty.Register("ControlToFocusOn", typeof(Control), typeof(EnhancedBusyIndicator), null);
public Control ControlToFocusOn
{
get { return (Control)GetValue(ControlToFocusOnProperty); }
set { SetValue(ControlToFocusOnProperty, value); }
}
protected override void OnIsBusyChanged(DependencyPropertyChangedEventArgs e)
{
base.OnIsBusyChanged(e);
if (AllowedToFocus && !IsBusy)
{
Dispatcher.BeginInvoke(() => { ControlToFocusOn.Focus(); });
AllowedToFocus = false;
}
}
}
To use it, replace the BusyIndicator
tags in your xaml with the new EnhancedBusyIndicator
and add the appropriate namespace.
Add a new property, ControlToFocusOn
inside the element, and bind it to an existing element in the view that you want focus to be on after the EnhancedBusyIndicator
disappears:
<my:EnhancedBusyIndicator
ControlToFocusOn="{Binding ElementName=NameTextBox}"
...
>
...
</my:EnhancedBusyIndicator>
In this case, I focused to a textbox called NameTextBox
.
That's it. This control will get focus every time we navigate to the page. While we are on the page, if the EnhancedBusyIndicator
becomes busy and not busy agiain, focus will not go to the control; this only happens on initial load.
If you want to allow the EnhancedBusyIndicator
to focus to the ControlToFocusOn
another time, add another property, AllowedToFocus
:
<my:EnhancedBusyIndicator
ControlToFocusOn="{Binding ElementName=NameTextBox}"
AllowedToFocus="{Binding IsAllowedToFocus}"
...
>
...
</my:EnhancedBusyIndicator>
When AllowedToFocus
is set to true, the next time EnhancedBusyIndicator
switches from busy to not busy, focus will go to ControlToFocusOn
.
AllowedToFocus can also be set to false when loading the view, to prevent focus from going to a control. If you bind AllowedToFocus
to a ViewModel property, you may need to change the BindingMode
. By default, it is OneTime
.
@Matt, not sure
DataContext="{Binding RelativeSource={RelativeSource Self}}"
will work in Silverlight 5, have you tried binding it as a static resource?