Wpf 新值为空时还原为原始值

Wpf 新值为空时还原为原始值,wpf,binding,mvvm,Wpf,Binding,Mvvm,警告——说到WPF,我是个新手。所以我要做的是在ViewModel中创建一个绑定到字符串属性的文本框。当用户清除文本框时,我希望它自动返回到用户最初的状态(当窗口打开时)。基本上,我阻止用户清除文本框 public RelayCommand SourceNameLostFocusCommand { get { return new RelayCommand(() => { if (string.I

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

public RelayCommand SourceNameLostFocusCommand
{
    get 
    { 
        return new RelayCommand(() => 
            {
                if (string.IsNullOrWhiteSpace(this.SourceName))
                    this.SourceName = this.configuredSource.Title;
            }); 
    }
}
目前,我的WPF将绑定设置为双向,并且我将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");
        }
    }
}
我遇到的问题是,我认为视图忽略了我的“RaisePropertyChanged”,因为我设置了UpdateSourceTrigger。如果我取出触发器,那么这是可行的,但是我必须失去对控件的关注,才能更新UI。因此,如果可以的话,我想保留触发器


如果用户清除文本框,有没有人能找到一种恢复原始值的好方法?

问题不在于
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访问
调度程序的标准方法(除非MVVM框架提供)。我通常将其包装在一个服务中,该服务具有一个用于同步和异步调用的良好接口,如上图所示


无论如何,关键是WPF这次将获得该事件,因为它位于单独的消息中。因此,UI将反映您的更改。

我让它工作起来了。解决方案是将我的属性设置为“dumber”,并允许将其设置为空

public string SourceName
{
    get { return this.sourceName; }
    set
    {
        if (!this.sourceName.Equals(value, StringComparison.OrdinalIgnoreCase))
        {
            this.sourceName = value;
            RaisePropertyChanged("SourceName");
        }
    }
}
然后我会有一个RelayCommand(MVVM灯),每当文本框上的焦点丢失时就会触发它

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>
xmlns:cmd=“clr命名空间:GalaSoft.MvvmLight.Command;assembly=GalaSoft.MvvmLight.Extras.WPF4”
xmlns:i=”http://schemas.microsoft.com/expression/2010/interactivity"

您可以发布相关的XAML吗?我会看看是否可以访问dispatcher,但我猜我不能。无法访问dispatcher@Travyguy9你试了什么?您始终可以通过
dispatcher.CurrentDispatcher
访问dispatcher。不过,我倾向于将其包装在服务中。@KentBoogaart同步环境不够好吗?这有效地实现了与我的建议相同的效果,但以一种更加迂回的方式。也就是说,它会导致属性在单独的调度程序消息中发生更改。但是现在您已经使实现复杂化,并使视图也依赖于它。当我无法访问dispatcher时,我就无能为力了。您确实可以访问dispatcher。请再次阅读我的答案和我答案中的评论。