2013-11-21 97 views
0

我正在構建WPF MVVM應用程序,但我在從子視圖模型更新父視圖時遇到問題。從子MVVM更新父視圖

我在我的父視圖模型上調用了doAction()方法,它更新了一個屬性並引發了一個PropertyChangeEvent。當從MainViewModel調用此方法時,一切都很好,但是當我從子視圖模型調用相同的方法時,PropertyChangedEvent get引發,但視圖不更新。

例子:

ChildViewModel() 
{ 
    private ParentViewModel parent; 

    parent.doAction(); // Raised event but MainView doesn't update 
} 

ParentViewModel() 
{ 
    public void doAction() 
    { 
     this.Property = true; 
     OnPropertyChange("Property"); 
    } 
} 

我的意見是使用XAML創建:

<MainView> 
    <TabItem> 
     <view:ChildView/> 
    </TabItem> 
</MainView> 

屬性格式更改事件引發像這樣:

protected void OnPropertyChanged(string name) 
{ 
    LOGGER.Info("Property Changed: " + name); 
    PropertyChangedEventHandler handler = PropertyChanged; 
    if (handler != null) 
    { 
     handler(this, new PropertyChangedEventArgs(name)); 
    } 
} 

我的問題是我怎麼得到父視圖來監聽和更新由子視圖引發的屬性更改事件。

編輯:

基類:

public abstract class AbstractBaseViewModel : INotifyPropertyChanged 
{ 

     public event PropertyChangedEventHandler PropertyChanged; 
     public ICommand CloseCommand { get; set; } 

     public AbstractBaseViewModel() 
     { 
      this.CloseCommand = new CloseCommand(this); 
     } 

     public void CloseWindow() 
     { 
      Application.Current.MainWindow.Close(); 
     } 

     protected void OnPropertyChanged(string name) 
     { 
      LOGGER.Info("Property Changed: " + name); 
      PropertyChangedEventHandler handler = PropertyChanged; 
      if (handler != null) 
      { 
       handler(this, new PropertyChangedEventArgs(name)); 
      } 
     } 
} 

父視圖模型:

public class ParentViewModel : AbstractBaseViewModel 
{ 
     private Dispatcher dispatcher; 
     private bool visible; 

     public bool Visible 
     { 
      get { return visible; } 
      set { visible= value; OnPropertyChanged("Visible"); } 
     } 

     public MainWindowViewModel() 
     { 
      this.dispatcher = Dispatcher.CurrentDispatcher; 
      this.manager = manager; 
     } 

     public void ShowTab(){ 
      this.Visible = true; 
     } 
} 

子視圖型號:

public class ChildViewModel : AbstractBaseViewModel 
{ 

    private ParentViewModel parentVm; 

    public GeneralViewModel(ParentViewModel vm) 
    { 
     this.parentVm= vm; 
    } 

    public void Command(){ 
     vm.ShowTab(); 
    } 
} 

ParentView的XAML:

<TabItem Header="ViewWeWantToHide/Show" 
    Visibility="{Binding Visible,Converter={converter:BooleanToVisibilityConverter}}"> 
    <views:SomeOtherView/> 
</TabItem> 

<TabItem Header="ChildView Tab"> 
    <views:ChildView/> 
</TabItem> 
+2

我沒有看到你的代碼中的任何問題(除非你在提高,改變屬性的功能'PropertyChanged'事件,而不是的財產二傳手)。請發佈完整的代碼,並提供更多描述。 –

+0

發佈XAML以向我們展示您使用該「Property」的位置。 – sthotakura

+0

愚蠢的問題,但你絕對派生自你的ParentViewModel INotifyPropertyChanged? – GazTheDestroyer

回答

0

謝謝大家的支持。

我發現與WPF無關的問題,實際上是我如何在我的子視圖上設置datacontext的產品。在我的父窗口中,我使用Unity容器創建並註冊了ParentViewModel的單例實例。這個實例會被注入到所有的子視圖中,問題是InitializeComponent方法在我的父視圖模型被創建並被註冊到unity容器之前被調用,這意味着所有的子視圖都完全接收到一個不同的實例。

不工作:

public MainWindow() 
{ 

    InitializeComponent(); 

    if (DesignerProperties.GetIsInDesignMode(this)) 
    { 
     this.DataContext = new ParentViewModel(); 
    } 
    else 
    {  
     IUnityContainer container = UnityFactory.Retrieve(); 

     ParentViewModel parentVM = container.Resolve<ParentViewModel>(); 
     container.RegisterInstance<ParentViewModel>(parentVM); 

     this.DataContext = parentVM; 

    } 
} 

工作:

public MainWindow() 
{ 

    if (DesignerProperties.GetIsInDesignMode(this)) 
    { 
     this.DataContext = new ParentViewModel(); 
    } 
    else 
    {  
     IUnityContainer container = UnityFactory.Retrieve(); 

     ParentViewModel parentVM = container.Resolve<ParentViewModel>(); 
     container.RegisterInstance<ParentViewModel>(parentVM); 

     this.DataContext = parentVM; 
    } 

    /** 
     * Initialize after registering parent VM and setting the datacontext 
     */ 
    InitializeComponent(); 

    } 
1

沒有看到你所有的代碼,很難猜測是什麼導致你的問題。不過,我不得不說,在WPF中顯示視圖模型實例在WP中更常見,並讓WPF自動顯示相關視圖,而不是像現在那樣直接顯示視圖。如果您使用視圖模型而不是視圖,那麼您將可以從父視圖模型訪問子視圖模型。

如果您確實或有權訪問父視圖模型中的子視圖模型,那麼我會建議您使用簡單的delegate來將子視圖模型「傳遞消息」傳遞給父視圖模型。你甚至可以定義一個無參數的參數delegate,並用它來發送一個信號,而不是任何屬性值。

您可以聲明delegate,將該類型的屬性添加到子女UserControl並在主視圖模型中附加處理程序。然後,您可以從子女UserControl中調用delegate,並在父視圖模型的處理程序中調用您的方法。有關此技術的更多信息,請參閱我對Passing parameters between viewmodels問題的回答(它回答了類似但不完全相同的問題)。

+0

嗨謝里丹, 我已更新我的問題,更多的代碼供您摘要。 我已經構建了應用程序的方式是,我宣佈鑑於我的主要view'ss XAML像這樣: <意見:NewView的/> NewView的的構造函數使用統一解決這個視圖模型對這一觀點和集Datacontext。 public NewView(){ this.DataContext = Unity.Resolve (); } 這種方法有什麼問題嗎?我應該使用不同的方法來實例化視圖併爲其分配視圖模型。 –

+0

不,儘管我沒有親身體驗Unity,但我知道它很受尊重和喜愛。由於WPF是如此以數據爲中心的,所以對於數據(在這種情況下是視圖模型並讓框架負責顯示UI和視圖)看起來合乎邏輯(至少對我來說)是合乎邏輯的。如果你喜歡這樣工作,那很好,但我不能告訴你如何讓Unity按照我的建議去做。 – Sheridan

+0

沒問題,謝謝你的反饋。至於基本問題,你有什麼建議,爲什麼從另一個視圖模型引發PropertyChangeEvent不更新主視圖? –