views:

117

answers:

2

In the example below:

  • I start program, type text, click button, see text above. Press ENTER see text again.

BUT:

  • I start program, type text, press ENTER, see no text.

It seems that the KeyDown event doesn't get access to the current value of the bound variable, as if it is always "one behind".

What do I have to change so that when I press ENTER I have access to the value that is in the textbox so I can add it to the chat window?

alt text

XAML:

<Window x:Class="TestScroll.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="290" Width="300" Background="#eee">
    <StackPanel Margin="10">

        <ScrollViewer Height="200" Width="260" Margin="0 0 0 10"
                      VerticalScrollBarVisibility="Auto"
                      HorizontalScrollBarVisibility="Auto">
            <TextBlock Text="{Binding TextContent}"
                       Background="#fff"/>
        </ScrollViewer>

        <StackPanel HorizontalAlignment="Left" Orientation="Horizontal">
            <TextBox x:Name="TheLineTextBox" 
                     Text="{Binding TheLine}" 
                     Width="205" 
                     Margin="0 0 5 0"
                     KeyDown="TheLineTextBox_KeyDown"/>
            <Button Content="Enter" Click="Button_Click"/>
        </StackPanel>

    </StackPanel>
</Window>

Code-Behind:

using System;
using System.Windows;
using System.Windows.Input;
using System.ComponentModel;

namespace TestScroll
{
    public partial class Window1 : Window, INotifyPropertyChanged
    {

        #region ViewModelProperty: TextContent
        private string _textContent;
        public string TextContent
        {
            get
            {
                return _textContent;
            }

            set
            {
                _textContent = value;
                OnPropertyChanged("TextContent");
            }
        }
        #endregion

        #region ViewModelProperty: TheLine
        private string _theLine;
        public string TheLine
        {
            get
            {
                return _theLine;
            }

            set
            {
                _theLine = value;
                OnPropertyChanged("TheLine");
            }
        }
        #endregion

        public Window1()
        {
            InitializeComponent();
            DataContext = this;
            TheLineTextBox.Focus();

        }

        private void Button_Click(object sender, RoutedEventArgs e)
        {
            AddLine();
        }

        void AddLine()
        {
            TextContent += TheLine + Environment.NewLine;
        }

        private void TheLineTextBox_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Return)
            {
                AddLine();
            }
        }

        #region INotifiedProperty Block
        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            PropertyChangedEventHandler handler = PropertyChanged;

            if (handler != null)
            {
                handler(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion
    }
}
+1  A: 

Does it work if you change AddLine to use TheLineTextBox.Text?

    void AddLine() 
    { 
        TextContent += TheLineTextBox.Text + Environment.NewLine; 
    } 
Gabe
yes, referencing it directly like that works, but I would like to find a solution which can use the data bindings just to keep things more loosely coupled, I had the x:name actually only for the focus.
Edward Tanguay
+3  A: 

Your textbox->property binding is only happening after the textbox loses focus. When you type in text and press enter, you have not set the focus anywhere else on the form. You can demonstrate this by typing in your text, clicking on the scroll viewer, then clicking back on the textbox and hitting enter. You will then see your text change in the viewer.

To get around that, update your Text property of the textbox to this.

Text="{Binding TheLine, UpdateSourceTrigger=PropertyChanged}"

http://blogs.msdn.com/wpfsdk/archive/2006/10/19/wpf-basic-data-binding-faq.aspx

See about a quarter of the way down the page: How do I make my data-bound TextBox update the source value as I type?

Anthony Pegram
yes, that's it, thanks!
Edward Tanguay
FYI: Be aware that every change is now being sent -- which might cause validation, (RIA validation, etc.) to occur at great expense. Sometimes, it's OK and what you want, but other times ... (that's why the default is the way it is).
WPCoder