2012-07-16 89 views
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更新。因此,爲什麼我想保持觸發器,如果​​我可以。

如果用戶清除文本框,任何人都可以很好地恢復到原始值?

+0

您可以發佈相關的XAML? – CodingGorilla 2012-07-16 17:46:14

回答

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(除非你的MVVM框架提供了一個)。我通常將其包裝在一個具有良好界面的服務中,以同步和異步方式調用,如上所示。

無論如何,問題在於WPF會在這一次得到這個事件,因爲它在一個單獨的消息中。因此,用戶界面將反映您的變化。

+0

生病看我是否可以訪問調度員,但我猜我不能。 – Travyguy9 2012-07-16 19:22:49

+0

無法訪問調度員 – Travyguy9 2012-07-16 20:04:44

+0

@ Travyguy9:你嘗試過什麼?您始終可以通過Dispatcher.CurrentDispatcher訪問調度程序。我傾向於將其包裝在一項服務中。 – 2012-07-16 20:49:34

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> 
+0

這有效地達到了我提議的效果,但是以更迂迴的方式實現。也就是說,它會導致屬性在單獨的調度程序消息中更改。但是現在你已經使實現複雜化了,並且也使得視圖也依賴於它。 – 2012-07-16 20:51:35

+0

當我無法訪問調度程序時,我無能爲力。 – Travyguy9 2012-07-17 13:10:10

+0

你*有*可以訪問調度員。請再次閱讀我的答案和評論。 – 2012-07-17 14:06:16