OnPropertyChanged上的WPF TextBox值不会更改

时间:2010-06-16 17:47:32

标签: wpf mvvm binding textbox

我有一个TextBox,其Value绑定到ViewModel属性:

        <TextBox Name="txtRunAfter" Grid.Column="4" Text="{Binding Mode=TwoWay, Path=RunAfter}" Style="{StaticResource TestStepTextBox}"/>

set和get工作正常,直到我设置Value时添加一些验证:

    private int _runAfter = 0;
    public string RunAfter
    {
        get
        {
            return _runAfter.ToString();
        }

        set
        {
            int val = int.Parse(value);

            if (_runAfter != val)
            {
                if (val < _order)
                    _runAfter = val;
                else
                {
                    _runAfter = 0;
                    OnPropertyChanged("RunAfter");
                }
            }
        }
    }

虽然已达到OnPropertyChanged(我已经相同),但视图不会更改。 我怎样才能做到这一点?

谢谢, JoséTavares

3 个答案:

答案 0 :(得分:5)

问题是,在Binding更新您的媒体资源时,您正在更新Binding的来源。 WPF在响应PropertyChanged更新时引发Binding事件时,实际上不会检查您的属性值。您可以使用Dispatcher来延迟事件在该分支中的传播来解决此问题:

set
{
    int val = int.Parse(value);

    if (_runAfter != val)
    {
        if (val < _order)
        {
            _runAfter = val;
            OnPropertyChanged("RunAfter");
        }
        else
        {
            _runAfter = 0;
            Dispatcher.CurrentDispatcher.BeginInvoke(
                new Action<String>(OnPropertyChanged), 
                DispatcherPriority.DataBind, "RunAfter");
        }
    }
}

<强>更新

我注意到的另一件事是Binding上的TextBox使用的是默认UpdateSourceTrigger,当TextBox失去焦点时会发生这种情况。在此TextBox失去焦点之后,您才会看到文本更改回0。如果您将其更改为PropertyChanged,您会立即看到这种情况。否则,在TextBox失去焦点之前,您的财产将无法设置:

<TextBox Name="txtRunAfter" Grid.Column="4" Text="{Binding RunAfter, UpdateSourceTrigger=PropertyChanged}" Style="{StaticResource TestStepTextBox}"/>

答案 1 :(得分:3)

我在这里注意到的一些事情。

除非你有令人信服的理由将RunAfter属性公开为字符串,否则没有理由不能将它作为int。这样可以节省你在setter中的强制转换(以及如果用户在字段中输入非整数的东西,可能会出现潜在的InvalidCastException)。

其次,OnPropertyChanged()调用应该发生在内部if语句之外,如下所示:

if(_runAfter != val)
{
    if(val < _order)
        _runAfter = val;
    else
        _runAfter = 0;
    OnPropertyChanged("RunAfter");
}

由于在条件的两个路径中都更新了_runAfter本地,因此无论采用哪个分支,都必须调用OnPropertyChanged()。我希望这有助于指明你正确的方向!

答案 2 :(得分:1)

我有同样的情况。我写了以下内容并且有效。

<TextBox Grid.Column="3" Grid.Row="0" HorizontalAlignment="Left" VerticalAlignment="Center" Width="100" Text="{Binding Path=FirstName}"></TextBox>

并且

public string FirstName
    {
        get { return _client.FirstName; }
        set
        {
            if (value == _client.FirstName)
                return;
            else
                _client.FirstName = value;
            OnPropertyChanged("FirstName");
        }
    }