10

TextBox を持つ WPF ビューがあり、Text フィールドを ViewModel にバインドし、UpdateSourceTrigger を PropertyChanged に設定しています。ViewModel のプロパティ セッターでは、テキストが 10 文字を超えないようにするための簡単なチェックを行います。

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

public partial class MainWindow : Window
{
    public MainWindow()
    {
        InitializeComponent();

        this.DataContext = new MainViewModel();
    }
}


public string Name
{
    get { return _Name; }
    set
    {
        if (_Name != value)
        {
            if (value.Length <= 10)
            {
                _Name = value;
            }
            RaisePropertyChanged("Name");
        }
    }
}

値が設定されていない場合でも、RaisePropertyChanged (PropertyChanged を起動するだけです) を実行します。

問題は、UI で 11 番目の文字を入力すると、_Name が更新されないことです。PropertyChanged を起動すると、get アクセサーが呼び出され、10 文字のみの文字列が返されることがわかります。ただし、私の TextBox はこれを反映していません。11 文字の文字列が引き続き表示されます。

その上、11 番目の文字でセッターのテキストを「ERROR」に変更し、fire プロパティを変更すると、TextBox が更新されて変更されたテキストが表示されます。

では、セッターのテキストを以前の値に戻しても、UI に反映されないのはなぜですか?

最大文字数を処理する別の方法があることは知っていますが、なぜこれがうまくいかないのでしょうか?

4

1 に答える 1

24

これはフレームワークのバグに他なりません。のTextプロパティはTextBox新しい値を取得しますが、GUIはそれ自体のプロパティと同期していませんTextProperty。これは、ViewModelからのItemsControl変更をキャンセルしたい場合にも発生し、非常に煩わしいものです。SelectedItem

ただし、 explicitを使用した場合、このバグは発生しないBindingため、回避策として使用できます。

Xaml

<TextBox Text="{Binding Path=MyName,
                        UpdateSourceTrigger=Explicit}"
         TextChanged="TextBox_TextChanged"/>

背後にあるコード

private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
    TextBox textBox = sender as TextBox;
    textBox.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}

TextBox GUIが実際に同期していないことを確認するには、の値を確認しますTextBox.TextTextBoxたとえば、「123456789 ___ 0」と表示され、「TextBlock123456789」と表示されます。

<StackPanel>
    <TextBox Name="myTextBox"
             Text="{Binding Path=MyName,
                            UpdateSourceTrigger=PropertyChanged}"/>
    <TextBlock Text="{Binding ElementName=myTextBox, Path=Text}"/>
</StackPanel>
于 2012-05-31T20:40:39.027 に答える