2013-10-14 20 views
2

我遇到更新我正在處理的Windows Phone 7應用程序接口的問題。從另一個視圖模型調用函數時,RaisePropertyChanged不會觸發

我有一個MainPage.xaml及其MainViewModel.cs它處理子視圖usercontrol ChildView1.xaml如何出現在MainPage中。 ChildView1也有它的ViewModel,它是Child1ViewModel.cs。基本上,一個myToggleButton被從MainPage觸發,這將觸發DataStateBehavior進入顯示或隱藏狀態,分別顯示或隱藏ChildView1.xaml。 DataStateBehavior被綁定到布爾CanShowView,而myToggleButton被綁定到名爲ButtonCheckedIcommand,後者具有中繼功能SwitchVisibility,該功能將反轉CanShowView布爾值以顯示或隱藏視圖。所有作品都很好,這要歸功於我使用的MVVM燈的RaisePropertyChanged

然而,ChildView1.xaml具有應該調用從MainViewModel的SwitchVisibility功能這又將恢復的CanShowViewCanShowViewRaisePropertyChanged應該解僱有ChildView1接近一個myCloseButton,但問題是,鑑於保持可見和從不關閉,出於某種原因!我通過調試器注意到CanShowView中的RaisePropertyChanged似乎不能啓動。我想這就是問題所在。我做錯了什麼?我該如何強制它開火?我使用了多個RaisePropertyChanged,但即使脫脂劑顯示我的功能中的值確實發生了變化,但似乎沒有任何火災發生。

這是我的代碼。 MainPage.xaml中:

<phone:PhoneApplicationPage 
    ... 
> 
    <phone:PhoneApplicationPage.DataContext> 
     <Binding Path="Main" Source="{StaticResource Locator}"/> 
    </phone:PhoneApplicationPage.DataContext> 
    ... 
    <Grid x:Name="LayoutRoot"> 
     ... 
     <ToggleButton x:Name="myToggleButton" Command="{Binding Main.ButtonChecked, Source={StaticResource Locator}}" > 
     <local:ChildView1 x:Name="myChildView1" Grid.Row="0" RenderTransformOrigin="0.5,0.5"> 
      <i:Interaction.Behaviors> 
      <ec:DataStateBehavior Binding="{Binding Main.CanShowView, Source={StaticResource Locator}}" Value="True" TrueState="showChildView1" FalseState="hideChildView1"/> 
     </i:Interaction.Behaviors> 
     <local:ChildView1.RenderTransform> 
      <CompositeTransform/> 
     </local:ChildView1.RenderTransform> 
     </local:ChildView1> 
    </Grid> 
</phone:PhoneApplicationPage>  

MainViewModel.cs:

public class MainViewModel : ViewModelBase 
{ 
    public ICommand ButtonChecked { get; private set; } 

    public MainViewModel() 
    { 
     ButtonChecked = new RelayCommand(() => SwitchVisibility()); 
    } 

    public void SwitchVisibility() 
    { 
     CanShowView = !CanShowView; 
     RaisePropertyChanged("CanShowView"); 
    } 

    bool _canShowView = true; 
    public bool CanShowView 
    { 
     get { return _canShowView; } 
     set 
     { 
      if (value != _canShowView) 
      { 
       _canShowView = value; 
       RaisePropertyChanged("CanShowView"); 
      } 
     } 
    } 

} 

ChildView1.xaml:

<UserControl x:Class="myApp.Views.ChildView1" 
.... 
DataContext="{Binding Child1VM, Source={StaticResource Locator}}" 
> 

    <Grid x:Name="HomeGrid"> 
     <Button x:Name=myCloseButton Command="{Binding Child1VM.CloseChildViewCmd, Source={StaticResource Locator}}"/> 
     ... 
    </Grid> 
</UserControl> 

Child1ViewModel.cs:

namespace myApp 
{ 
    public class Child1ViewModel : ViewModelBase 
    { 
     public ICommand CloseChildViewCmd { get; private set; } 
     public Child1ViewModel() 
     { 
      CloseChildViewCmd = new RelayCommand(() => ExecuteCloseChildViewCmd()); 
     } 

     public void ExecuteCloseChildViewCmd() 
     { 
      MainPage mainPage = new MainPage(); 
      MainViewModel mainVM = new MainViewModel(); 
      mainPage.DataContext = mainVM; 
      mainVM.SwitchVisibility(); 

     } 
    } 
} 

注:我只初學者p程序員,所以我解決問題的方式或程序本身可能是有問題的,因此我願意接受任何建議,並且代碼示例非常受歡迎。在做了大量研究和嘗試了許多似乎無法工作的事情後,我一直堅持這個問題很多天了。我花時間詳細寫下了這個問題,我真的很希望我能在這裏找到解決方案。如果有更多的細節需要知道,請告訴我。 在此先感謝。

編輯:我讀了創建視圖的新實例不是解決方案。我還能如何訪問MainView的函數並提升屬性?

編輯:正如OmegaMan所建議的,我使用靜態定義來調用我的函數。 所以更新MainViewModel.cs: public class MainViewModel:ViewModelBase { public ICommand ButtonChecked {get;私人設置; } private static MainViewModel Primary {get;組; }

public MainViewModel() 
    { 
     ButtonChecked = new RelayCommand(() => SwitchVisibility()); 
     Primary = this; 
    } 

    public void SwitchVisibility() 
    { 
     CanShowView = !CanShowView; 
     RaisePropertyChanged("CanShowView"); 
    } 

    public static void SwitchViewStatic() 
    { 
     Primary.SwitchVisibility(); 
    } 

    bool _canShowView = true; 
    public bool CanShowView 
    { 
     get { return _canShowView; } 
     set 
     { 
      if (value != _canShowView) 
      { 
       _canShowView = value; 
       RaisePropertyChanged("CanShowView"); 
      } 
     } 
    } 

} 

更新Child1ViewModel.cs: 命名空間對myApp { 公共類Child1ViewModel:ViewModelBase { 公衆的ICommand CloseChildViewCmd {獲得;私人設置; } public Child1ViewModel() { CloseChildViewCmd = new RelayCommand((=)ExecuteCloseChildViewCmd()); }

 public void ExecuteCloseChildViewCmd() 
     { 
      MainViewModel.SwitchViewStatic(); 

     } 
    } 
} 

在MainViewModel所需的功能得到由myCloseButton從子視圖調用,但仍然CanShowView不會得到提高到允許DataStateBehavior聽着它,更新UI ...所以我仍然無所事事。

+0

其中MVVM框架靜態方法訪問? –

回答

1

讓孩子持有對主視圖模型的引用沒有錯,但爲什麼控件創建一個新的MainViewModel?傳遞MainViewModel並關閉它的SwitchVisibility ...或者在MainVM上創建一個靜態方法,它將訪問實際的VM並調用實例SwitchVisiblity。

---更新您使用的顯示從MainVM

public class MainViewModel : ViewModelBase 
{ 
    private static MainViewModel Primary { get; set; } 

    public MainViewModel() 
    { 
     Primary = this; 
    } 

    public static void SwitchViewStatic() 
    { 
     Primary.SwitchVisibility(); 
    } 

    public void SwitchVisibility() 
    { 
    ... 
    } 

} 
+0

是的,它確實是錯誤的。就像我對McGarnagle說的那樣,我認爲我會在某個地方看到它會調用最新的應用程序狀態。在我以前的嘗試中,我沒有實例化視圖,仍然無法提出屬性。對於靜態方法,你的意思是我可以創建例如'公共靜態無效LaunchSwitcher(){SwitchVisibility();}'並從子視圖調用該方法?如果是這樣,我怎麼會從該子視圖模型調用該方法,而不實例化主視圖,或者它不重要?謝謝回覆。 – JNate

+0

@JNate對於靜態方法的想法,讓虛擬機的構造函數自己填充到一個靜態變量(本例)中。然後讓靜態方法使用該靜態變量並調用SwitchVisibility。 – OmegaMan

+0

我研究了爲了存儲MainViewModel而創建靜態變量的位置,但沒有運氣。你的意思是像'public static var myVar = this'在MainViewModel中定義的嗎?我試圖定義它,但是我在var和this上收到了錯誤消息。我應該在什麼時候定義它。這是什麼意思的靜態變量,將調用MainViewModel? 如果我能夠創建myVar,我相信這是它應該做的: 'public static void LaunchSwitcher(){myVar.SwitchVisibility();}' 正確嗎? – JNate

1

問題是,您正在向新的MainPage對象和視圖模型發送消息,而不是現有的消息。

你需要的是委託或事件。訣竅是將主頁連接到子頁面。

如果你需要保持它們分開,你需要一個對象來發送事件。這稱爲事件聚合器或信使。您的主視圖模型需要訂閱子視圖模型在執行命令時發送的CloseChild事件。事件聚合器傳輸消息。

注意:大多數MVVM框架都實現了您的視圖模型可以用來發送和接收消息/事件的某種信使。

如果您想自己實施一個,請參閱here以創建一個。

相關問題