当新值为空时,恢复为原始值

时间:2012-07-16 17:43:39

标签: wpf binding mvvm

警告 - 对于WPF,我是一个新手。所以我要做的是有一个文本框绑定到我的ViewModel中的字符串属性。当用户清除文本框时,我希望它自动返回到用户最初的状态(打开窗口时)。基本上我阻止用户清除文本框。

目前,我的WPF绑定为TwoWay,而且我确实将UpdateSourceTrigger设置为PropertyChanged。我想我想保留UpdateSourceTrigger,因为我喜欢我的ViewModel中的属性,以便在用户进行一点改动时获得更新。这样我可以在用户执行某些操作时执行其他UI操作(例如,更新我的“保存”按钮,因为用户更改了某些内容)。

我的ViewModel中的属性目前看起来像这样,我尝试使用原始值:

public string SourceName
{
    get { return this.sourceName; }
    set
    {
        if (!this.sourceName.Equals(value, StringComparison.OrdinalIgnoreCase))
        {
            if (!string.IsNullOrWhiteSpace(value))
                this.sourceName = value;
            else
                this.sourceName = this.configuredSource.Name;

            RaisePropertyChanged("SourceName");
        }
    }
}

我遇到的问题是我认为View忽略了我的'RaisePropertyChanged',因为我设置了UpdateSourceTrigger。如果我取出触发器,那么这是有效的,但我必须失去对控件的关注才能进行UI更新。因此,如果可以,我想保留触发器的原因。

如果用户清除文本框,任何人都有一种很好的方法可以恢复原始值吗?

2 个答案:

答案 0 :(得分:0)

问题不在于UpdateSourceTrigger,而是就WPF而言,它传递给你的财产的价值是它将承担的价值。它会忽略您为了避免递归循环而引发的属性更改事件。

您需要在单独的消息中引发事件,如下所示:

public string SourceName
{
    get { return this.sourceName; }
    set
    {
        if (!this.sourceName.Equals(value, StringComparison.OrdinalIgnoreCase))
        {
            if (!string.IsNullOrWhiteSpace(value))
            {
                this.sourceName = value;
                RaisePropertyChanged("SourceName");
            }
            else
            {
                this.sourceName = this.configuredSource.Name;
                this.dispatcherService.BeginInvoke(() => this.RaisePropertyChanged("SourceName"));
            }
        }
    }
}

这是一种伪代码,因为没有标准方法可以从您的VM访问Dispatcher(除非您的MVVM框架提供了一个)。我通常将它包装在一个具有良好接口的服务中,用于同步和异步调用,如上所示。

无论如何,重点是WPF这次会得到这个事件,因为它是在一个单独的消息中。因此,用户界面将反映您的更改。

答案 1 :(得分:0)

我得到了它的工作。解决方案是让我的财产成为'笨蛋'并允许它被设置为空。

public string SourceName
{
    get { return this.sourceName; }
    set
    {
        if (!this.sourceName.Equals(value, StringComparison.OrdinalIgnoreCase))
        {
            this.sourceName = value;
            RaisePropertyChanged("SourceName");
        }
    }
}

然后我会有一个RelayCommand(MVVM Light),当文本框上的焦点丢失时会被触发。

public RelayCommand SourceNameLostFocusCommand
{
    get 
    { 
        return new RelayCommand(() => 
            {
                if (string.IsNullOrWhiteSpace(this.SourceName))
                    this.SourceName = this.configuredSource.Title;
            }); 
    }
}

以下是我的xaml片段,让RelayCommand在失去焦点时触发:

xmlns:cmd="clr-namespace:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4"
xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"

<TextBox Text="{Binding Path=SourceName, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}">
   <i:Interaction.Triggers>
      <i:EventTrigger EventName="LostFocus">
         <cmd:EventToCommand Command="{Binding SourceNameLostFocusCommand, Mode=OneWay}" />
      </i:EventTrigger>
   </i:Interaction.Triggers>
</TextBox>