2010-07-09 39 views
0

我想在對象編輯過程中使用IsDirty標誌來控制CanExecute和Navigational控件。使用IsDirty與ICommands

問題是,爲了這個工作,我想我必須使用onPropertyChanged爲我的IsDirty方法,以便我的控件獲取更改通知。(我想要一些控件被禁用時,我的對象IsDirty)不幸的是,我得到討厭的計算器,因爲它盤旋到IsDirty ......嘿嘿的可怕循環..

有沒有人能夠得到一些類似的工作嗎?我所做的就是在我的OnPropertyChanged方法中將IsDirty設置爲true。然後,在我的canExecute方法中,我看到它是否設置爲true,但隨後在我的控件上,我需要Databind ...它導致了所有問題。

沒有人知道如何實現這樣的東西?

這是我的解決方案

::在ViewModelBase

Private _isdirty As Boolean = False 
     Protected Property IsDirty As Boolean 
      Get 
       Return _isdirty 
      End Get 
      Set(ByVal value As Boolean) 
       If _isdirty = Not value Then 
        _isdirty = value 
        If _isdirty = True Then 
         DisableNavigation() 
        Else 
         EnableNavigation() 
        End If 
       End If 
      End Set 
     End Property 

Private _haschanges As Boolean 
     Public Property HasChanges As Boolean 
      Get 
       Return _haschanges 
      End Get 
      Set(ByVal value As Boolean) 
       If value = Not _haschanges Then 
        _haschanges = value 
        OnPropertyChanged("HasChanges") 
       End If 
      End Set 
     End Property 



Protected Sub EnableNavigation() 
      'Keep from firing multiple onPropertyChanged events 
      If HasChanges = True Then 
       HasChanges = False 
      End If 

      GetEvent(Of DisableNavigationEvent).Publish(False) 

     End Sub 

     Protected Sub DisableNavigation() 
      'Keep from firing multiple onPropertyChanged events 
      If HasChanges = False Then 
       HasChanges = True 
      End If 
      GetEvent(Of DisableNavigationEvent).Publish(True) 

     End Sub 

::在EditViewModelBase從ViewModelBase派生的。

Protected Overrides Sub OnPropertyChanged(ByVal strPropertyName As String) 
      MyBase.OnPropertyChanged(strPropertyName) 

      If SetsIsDirty(strPropertyName) Then 
       If isLoading = False Then 

        IsDirty = True 
       Else 
        IsDirty = False 

       End If 
      End If 



     End Sub 
     ''' <summary> 
     ''' Helps prevent stackoverflows by filtering what gets checked for isDirty 
     ''' </summary> 
     ''' <param name="str"></param> 
     ''' <returns></returns> 
     ''' <remarks></remarks> 
     Protected Function SetsIsDirty(ByVal str As String) As Boolean 

      If str = "CurrentVisualState" Then Return False 
      If str = "TabsEnabled" Then Return False 
      If str = "IsLoading" Then Return False 
      If str = "EnableOfficeSelection" Then Return False 

      Return True 

     End Function 

::在我的ViewModel

Public ReadOnly Property SaveCommand() As ICommand 
      Get 
       If _cmdSave Is Nothing Then 
        _cmdSave = New RelayCommand(Of DoctorOffice)(AddressOf SaveExecute, Function() CanSaveExecute()) 
       End If 
       Return _cmdSave 
      End Get 
     End Property 

Private Function CanSaveExecute() As Boolean 
      'if the object is dirty you want to be able to save it. 
      Return IsDirty 

     End Function 

     Private Sub SaveExecute(ByVal param As DoctorOffice) 
      BeginWait() 
      GetService(Of Services.IDoctorOfficesService).Update(SelectedDoctorOffice, False) 
      EndWait() 

     End Sub 
+0

請粘貼您的IsDirty屬性和Execute/CanExecute事件處理程序的實現嗎? – 2010-07-09 21:51:18

回答

0

只是你的CanExecute斷言對於您的ICommand包括IsDirty屬性

例如

public class MyViewModel 
{ 
    public CanSave { get { return IsDirty;}} 
    public void Save(object parameter) 
    { 
    //Do stuff here 
    } 

    public ICommand SaveCommand = new RelayCommand(() => this.Save,() => this.CanSave); 
} 

,或者如果CanSave只引用IsDirty你可以設置你的ICommand是這樣的:

public ICommand SaveCommand = new RelayCommand(() => this.Save,() => this.IsDirty); 

只要RelayCommand使用CommandManager.RequerySuggestedCanExecuteChanged事件CanSave謂詞將隨時重新查詢任何有約束力的價值ViewModel中的更改。

這是一個很大的問題,因爲沒有CommandManager.RequerySuggested WPF不知道要更新UI。這可能會變得昂貴,因爲每次在視圖模型中更改任何值時,所有RelayCommand都會被重新查詢。但只要您的CanExecute謂詞是一個簡單的計算,它可能可以忽略不計,即如果您在CanExecute謂詞中調用數據庫或Web服務,則會出現一些嚴重的性能問題:)

+0

即時將標記爲你的正確,因爲它是最接近我需要做的事情,我沒有真正深入到一開始...... – ecathell 2010-07-13 14:13:43

1

避免堆棧溢出的最簡單方法是AA後衛條款您IsDirty屬性的setter:

public bool IsDirty 
{ 
    get { return _isDirty; } 
    set 
    { 
     if (_isDirty == value) 
      return; 
     _isDirty = value; 
     NotifyPropertyChanged("IsDirty"); 
    } 
} 

可惜只是這樣做,你如果您嘗試設置IsDirty = false,仍然會遇到問題,因爲您的PropertyChanged方法會重置爲true。爲避免這種情況,您應該檢查該方法中的屬性名稱,如果更改的屬性名稱爲「IsDirty」,則跳過IsDirty的設置。

+0

我實際上已經嘗試了這個東西,除了在二傳手中的守衛聲明......我也試過了。我有其他幾個'狀態'布爾值,我已經設置了一個方法,檢查,然後設置是骯髒的......生病發布一些代碼後,我得到它從工作遷移到家。 – ecathell 2010-07-10 12:58:47

0

您不需要通知IsDirty已更改。只要使它成爲一個普通的屬性或字段,它應該工作正常(並且沒有無限循環)。

這是假設你正在使用的RelayCommand,每個人都似乎在MSDN雜誌使用(有很好的理由)從Josh Smith's article

+0

如果你不提高notifyproperty改變你的標準控制不會知道他們需要刷新。 – ecathell 2010-07-13 14:12:13

+0

啊,錯過了關於禁用控件的部分 - 認爲它只是關於CanExecute。 – 2010-07-13 14:23:35

相關問題