Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Focus an TextBox on Button click

Tags:

c#

mvvm

wpf

xaml

So how to Focus an TextBox on Button click using the MVVM Pattern?

i created an simple Testproject Based on this Answer which works on the first click, but after that it doesn't set the Focus anymore. What do i miss?

XAML (View)

<Grid>
    <TextBox Height='23' HorizontalAlignment='Left' Margin='12,12,0,0' VerticalAlignment='Top' Width='120'
             Text='{Binding TheText}'
             local:FocusExtension.IsFocused="{Binding IsFocused}"/>
    <Button Content='Click' Height='23' HorizontalAlignment='Left' Margin='138,11,0,0' VerticalAlignment='Top' Width='75' 
            Command='{Binding ClickCommand}'/>
    <Button Content='Just to deFocus' Height='28' HorizontalAlignment='Left' Margin='14,44,0,0' Name='button1' VerticalAlignment='Top' Width='199' />
</Grid>

ViewModel

public class ViewModel : INotifyPropertyChanged
{
    public string TheText { get; set; }
    public bool IsFocused { get; set; }

    private RelayCommand _clickCommand;
    public ICommand ClickCommand
    {
        get { return _clickCommand ?? (_clickCommand = new RelayCommand(param => this.OnClick())); }
    }
    private void OnClick()
    {
        IsFocused = true;
        RaisePropertyChanged("IsFocused");
    }

    #region INotifyPropertyChanged

    public event PropertyChangedEventHandler PropertyChanged;

    public void RaisePropertyChanged(string propName)
    {
        if (this.PropertyChanged != null)
            this.PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }

    #endregion
}

and here is an Download link with an ready to go Project(VS2010) for the lazy ones ;)

like image 383
WiiMaxx Avatar asked Oct 17 '25 10:10

WiiMaxx


1 Answers

Your attached property value is never going back to false after the initial default is overwritten. hence your FocusExtension class is not calling Focus() on the TextBox since the PropertyChanged does not need to fire when setting IsFocused in your VM to true.

switch the OnIsFocusedPropertyChanged(...)

from:

private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    var uie = (UIElement)d;
    if ((bool)e.NewValue)
        uie.Focus(); // Don't care about false values.
}

to

private static void OnIsFocusedPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
  var uie = (UIElement)d;
  if (!((bool)e.NewValue))
    return;
  uie.Focus();
  uie.LostFocus += UieOnLostFocus;
}

private static void UieOnLostFocus(object sender, RoutedEventArgs routedEventArgs) {
  var uie = sender as UIElement;
  if (uie == null)
    return;
  uie.LostFocus -= UieOnLostFocus;
  uie.SetValue(IsFocusedProperty, false);
}

Update:

Along with the above change also make sure

local:FocusExtension.IsFocused="{Binding IsFocused}"

is switched to

local:FocusExtension.IsFocused="{Binding IsFocused, Mode=TwoWay}"

Working Download Link

Another Update

To set the Mode=TwoWay as default for this attached property in FocusExtension class switch

public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached(
  "IsFocused",
  typeof(bool),
  typeof(FocusExtension),
  new UIPropertyMetadata(
    false,
    OnIsFocusedPropertyChanged));

to

public static readonly DependencyProperty IsFocusedProperty = DependencyProperty.RegisterAttached(
  "IsFocused",
  typeof(bool),
  typeof(FocusExtension),
  new FrameworkPropertyMetadata(
    false,
    FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
    OnIsFocusedPropertyChanged));

You can skip explicitly specifying Mode=TwoWay in xaml with the above declaration.

like image 59
Viv Avatar answered Oct 18 '25 22:10

Viv