2017-07-13 41 views
0

MVVMをテストして(コードビハインドなしで)ビューを切り替えるために、かなり単純なWPFアプリケーションを構築しようとしています。起動時に、Def.xamlをロードしてボタンをクリックすると、ビューを切り替えることになっています。私が抱えている問題は、RelayCommandがボタンクリックイベントで発生していないようで、ビューは変更されていないということです。また、最初のビューを正しい方法で設定しているかどうかはわかりません。この点に関する助けがあれば、非常に感謝しています。次のように私のコードは次のとおりです。RelayCommandがコード内で実行されていません

AppViewModel.cs - これはMainWindow.xaml

namespace Test 
{ 
    class AppViewModel : ObservableObject 
    { 
     private ICommand ActivateView { get; set; } 
     private ICommand DeactivateView { get; set; } 

     public AppViewModel() 
     { 
      ActiveView = new DefViewModel(); 
      ActivateView = new RelayCommand(UnsetDef); 
      DeactivateView = new RelayCommand(SetDef); 
     } 

     private void UnsetDef(object obj) 
     { 
      ActiveView = new AltViewModel(); 
      MessageBox.Show("Done!"); 
     } 

     private void SetDef(object obj) 
     { 
      ActiveView = new DefViewModel(); 
     } 
    } 
} 

MainWindow.xaml

<Window x:Class="Test.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:local="clr-namespace:Test" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525"> 

    <Window.Resources> 
     <DataTemplate DataType="{x:Type local:DefViewModel}"> 
      <local:def/> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type local:AltViewModel}"> 
      <local:Alt/> 
     </DataTemplate> 
    </Window.Resources> 

    <Window.DataContext> 
     <local:AppViewModel/> 
    </Window.DataContext> 

    <Grid> 
     <ContentControl Content="{Binding Path=ActiveView}"/> 
    </Grid> 
</Window> 

Def.xamlためのViewModelにある - これは、私のデフォルトビューです

<UserControl x:Class="Test.def" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:Test" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <Grid> 
     <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center"> 
      <TextBlock Padding="15,15,15,15" Text="Default View Active"/> 
      <Button Padding="1,1,1,1" Content="Activate Alt View" Command="{Binding Path=ActivateView}"/> 
     </StackPanel> 
    </Grid> 
</UserControl> 

Alt.xaml - この私の代替図である

<UserControl x:Class="Test.Alt" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:local="clr-namespace:Test" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 
    <Grid> 
     <StackPanel VerticalAlignment="Center" HorizontalAlignment="Center"> 
      <TextBlock Padding="15,15,15,15" Text="Alt View Active"/> 
      <Button Padding="1,1,1,1" Content="Deactivate Alt View" Command="{Binding Path=DeactivateView}"/> 
     </StackPanel>   
    </Grid> 
</UserControl> 

ObservableObject.cs - これは私がINotifyPropertyChangedの

namespace Test 
{ 
    public abstract class ObservableObject : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

     private void OnPropertyChanged(string prop) 
     { 
      PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(prop)); 
     } 

     private object activeView; 
     public object ActiveView 
     { 
      get { return activeView; } 
      set { activeView = value; OnPropertyChanged("ActiveView"); } 
     } 
    } 
} 

RelayCommand.cs

を実装するために作られた抽象クラスです
namespace Test 
{ 
    class RelayCommand : ICommand 
    { 
     #region Fields 

     readonly Action<object> _execute; 
     readonly Predicate<object> _canExecute; 

     #endregion 

     public RelayCommand(Action<object> execute) : this(execute, null) { } 
     public RelayCommand(Action<object> execute, Predicate<object> canExecute) 
     { 
      _execute = execute ?? throw new ArgumentNullException("execute"); _canExecute = canExecute; 
     } 

     //private Action<object> _action; 

     //public RelayCommand(Action<object> action) 
     //{ 
     // _action = action; 
     //} 

     #region ICommand Members 

     public bool CanExecute(object parameter) 
     { 
      return _canExecute == null ? true : _canExecute(parameter); 
     } 

     public event EventHandler CanExecuteChanged 
     { 
      add { CommandManager.RequerySuggested += value; } 
      remove { CommandManager.RequerySuggested -= value; } 
     } 

     public void Execute(object parameter) 
     { 
      _execute(parameter); 
      //if(parameter != null) 
      //{ 
      // _action(parameter); 
      //} 
      //else 
      //{ 
      // _action("Nyet!"); 
      //} 
     } 

     #endregion 
    } 
} 

UPDATE:親のdatacontextが参照するためのバインディングを変更するbwingの提案。ありがとうございました!

答えて

1

あなたがバインドするコマンドは公開する必要があります。

また、実行時にコマンドを変更しない場合は、読み取り専用にすることもできます。

更新: もう1つの問題は、ボタンが間違ったDataContextにバインドされていることです。 ContentControlに適用されたテンプレートは、そのコンテキストとしてDefViewModelを取得します。

このように動作させるには、ActivateViewコマンドをDefViewModelに移動します。 または少し醜い解決策は、親datacontextを参照するようにバインディングを変更することです。

<Button Padding="1,1,1,1" Content="Activate Alt View" Command="{Binding Path=DataContext.ActivateView, RelativeSource={RelativeSource AncestorType={x:Type Window}}}"/> 
+0

私はすでに試してみましたが、まだ動作させることはできません。コマンドを読み取り専用にすることについてのヒントをありがとう! – pkoganti

+0

デバッグ用のバインディングの問題スヌープをダウンロードすることをお勧めします。 https://snoopwpf.codeplex.com/バインディングエラーを見つけるのに役立ちます。また、Visual Studioの[出力]ウィンドウでバインディングの失敗を確認することもできます。 – bwing

+0

それは働いた!具体的には、バインドを親データコンテキストを参照するように変更すると、そのトリックが実行されました。本当にありがとうございます! ActivateViewコマンドをDefViewModelに移動して、その動作を確認します。しかし、MVVMアーキテクチャに違反すると私は理解しています。あれは正しいですか? また、スヌープをおすすめしてくれてありがとうございます。私はより複雑なものを構築するので、私はそれを大いに活用するでしょう。 – pkoganti

関連する問題