Tomas Grosup
Tomas Grosup

Reputation: 6514

How do I change TextBox.Text without losing the binding in WPF?

In a WPF application, I am creating a setting window to customize keyboard shortcuts.

In the textboxes, I handle the KeyDown event and convert the Key event to a human readable form (and also the form in which I want to have my data).

The text box is declared like this

<TextBox Text="{Binding ShortCutText, Mode=TwoWay}"/>

and in the event handler, I tried using both

(sender as TextBox).Text = "...";

and

(sender as TextBox).Clear();
(sender as TextBox).AppendText("...");

In both of these cases, the binding back to the viewmodel does not work, the viewmodel still contains the old data and does not get updated. Binding in the other direction (from viewmodel to the textbox) works fine.

Is there a way I can edit the TextBox.Text from code without using the binding? Or is there an error somewhere else in my process?

Upvotes: 11

Views: 13104

Answers (8)

Rob van Daal
Rob van Daal

Reputation: 367

If your binding is destroyed by setting a new value (which is strange, for a two way binding the binding should stay intact), then use ((TextBox)sender).SetCurrentValue(TextBox.TextProperty, newValue) to leave the binding intact.

Upvotes: 2

Yochai Timmer
Yochai Timmer

Reputation: 49271

You can configure it in the xaml itself:

<TextBox Text="{Binding ShortCutText, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"/>

UpdateSourceTrigger=PropertyChanged

Upvotes: 1

xurxodev
xurxodev

Reputation: 1837

If you are using MVVM you should not change the Text property of the TextBox from code , change the value in the view model and the pattern will do its job synchronizing the view.

Upvotes: 0

Darlan Dieterich
Darlan Dieterich

Reputation: 2537

I have similar case.

When I clear the textbox this losing the Binding.

I wore: textbox1.Text = String.empty

I change for this: textbox1.Clear()

And this is point for my solution

Upvotes: 1

Yurii Zhukow
Yurii Zhukow

Reputation: 375

You don`t need to modify value of TextBox at all! In code you need only to modify your related value (ShortCutText) Also you can set IsReadOnly="True" property of your TextBox.

<TextBox Text="{Binding Path=ShortCutText,Mode=OneWay}" 
         KeyDown="TextBox_KeyDown" IsReadOnly="True"/>

You should realize INotifyPropertyChanged interface in your class as described in MSDN:

http://msdn.microsoft.com/library/system.componentmodel.inotifypropertychanged.aspx

Modify setter of your ShortCutText property (to which your TextBox is bound to):

class MyClass:INotifyPropertyChanged
{
    string shortCutText="Alt+A";
    public string ShortCutText
    {
         get { return shortCutText; } 
         set 
             { 
                  shortCutText=value; 
                  NotifyPropertyChanged("ShortCutText");
             }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    void NotifyPropertyChanged( string props )
    {
        if( PropertyChanged != null ) 
            PropertyChanged( this , new PropertyChangedEventArgs( prop ) );
    }

}

WPF will subscribe to the PropertyChanged event automatically. Now use KeyDown event of TextBox, for example, like this:

private void TextBox_KeyDown( object sender , KeyEventArgs e )
{
    ShortCutText = 
        ( e.KeyboardDevice.IsKeyDown( Key.LeftCtrl )? "Ctrl+ " : "" )
        + e.Key.ToString( );
}

Upvotes: 1

KyorCode
KyorCode

Reputation: 1497

var box = sender as TextBox;
// Change your box text..

box.GetBindingExpression(TextBox.TextProperty).UpdateSource();

This should force your binding to update.

Upvotes: 10

Tomas Grosup
Tomas Grosup

Reputation: 6514

This did the trick:

private static void SetText(TextBox textBox, string text)
    {
        textBox.Clear();
        textBox.AppendText(text);
        textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
    }

Upvotes: 2

Kieren Johnstone
Kieren Johnstone

Reputation: 42003

Don't change the Text property - change what you are binding to.

Upvotes: 3

Related Questions