I would like to show/activate a hidden window and set the (keyboard-)focus to a textbox programmatically (without violating mvvm if possible).
So if the the user presses a hotkey (already implemented) following should happen:
- Window gets shown + activated
- Textbox gets focused + keyboard focus (so the user can type some text)
Pressing the hotkey again should hide the window.
I tried binding Activated
and Visibility
to a boolean value, but I ran into some problems with TwoWay-Binding. Thank you for any ideas on how to solve this problem.
Edit:
MainWindow.xml:
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVisConverter" />
</Window.Resources>
<i:Interaction.Behaviors>
<bh:ActivateBehavior Activated="{Binding Visible, Mode=TwoWay}"/>
</i:Interaction.Behaviors>
<Window.Visibility>
<Binding Path="Visible" Mode="TwoWay" Converter="{StaticResource BoolToVisConverter}"/>
</Window.Visibility>
<TextBox Grid.Column="1" x:Name="SearchBar" bh:FocusExtension.IsFocused="{Binding Visible, Mode=TwoWay}"/>
ActivateBehavior.cs: used from this https://stackoverflow.com/a/12254217/13215602
public class ActivateBehavior : Behavior<Window> {
Boolean isActivated;
public static readonly DependencyProperty ActivatedProperty =
DependencyProperty.Register(
"Activated",
typeof(Boolean),
typeof(ActivateBehavior),
new PropertyMetadata(OnActivatedChanged)
);
public Boolean Activated {
get { return (Boolean) GetValue(ActivatedProperty); }
set { SetValue(ActivatedProperty, value); }
}
static void OnActivatedChanged(DependencyObject dependencyObject, DependencyPropertyChangedEventArgs e) {
var behavior = (ActivateBehavior) dependencyObject;
if (!behavior.Activated || behavior.isActivated)
return;
// The Activated property is set to true but the Activated event (tracked by the
// isActivated field) hasn't been fired. Go ahead and activate the window.
if (behavior.AssociatedObject.WindowState == WindowState.Minimized)
behavior.AssociatedObject.WindowState = WindowState.Normal;
behavior.AssociatedObject.Activate();
}
protected override void OnAttached() {
AssociatedObject.Activated += OnActivated;
AssociatedObject.Deactivated += OnDeactivated;
}
protected override void OnDetaching() {
AssociatedObject.Activated -= OnActivated;
AssociatedObject.Deactivated -= OnDeactivated;
}
void OnActivated(Object sender, EventArgs eventArgs) {
this.isActivated = true;
Activated = true;
}
void OnDeactivated(Object sender, EventArgs eventArgs) {
this.isActivated = false;
Activated = false;
}
}
FocusExtension.cs: used from this https://stackoverflow.com/a/1356781/13215602
public static class FocusExtension
{
public static bool GetIsFocuses(DependencyObject obj)
{
return (bool)obj.GetValue(IsFocusedProperty);
}
public static void SetIsFocused(DependencyObject obj, bool value)
{
obj.SetValue(IsFocusedProperty, value);
}
public static readonly DependencyProperty IsFocusedProperty =
DependencyProperty.RegisterAttached("IsFocused", typeof(bool), typeof(FocusExtension),
new UIPropertyMetadata(false, OnIsFocusedPropertyChanged));
private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var uie = (UIElement) d;
if ((bool) e.NewValue)
{
Keyboard.Focus(uie);
uie.Focus();
}
}
}
MainViewModel.cs:
private bool mVisible;
//Binding to this variable
public bool Visible
{
get { return mVisible; }
set
{
if (mVisible == value)
return;
mVisible = value;
RaisePropertyChanged(nameof(Visible));
}
}