0

警告——我是 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");
        }
    }
}

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

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

4

2 回答 2

0

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

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>
于 2012-07-16T20:31:53.437 回答
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"));
            }
        }
    }
}

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

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

于 2012-07-16T19:18:12.343 回答