2017-07-16 30 views
0

誰かが私を助けてくれることを願っています。投稿用のコードを簡略化しました。MVVMのViewModelにWPF CommandParameterを取る方法は?

メニュー付きのメインウィンドウ(MvvmTestView)と、いくつかのタブを保持する第2ウィンドウ(SettingsView)があります。私は、SettingsViewウィンドウをきれいに開くことができます。私はコードでこれを設定することでどのタブを開くかを選択することもできます。

XAMLコードからコマンドパラメータで正しい値を取得して正しいタブを開くにはどうすればよいですか?

MvvmTestView.xaml:

<Window x:Class="MvvmTest.Views.MvvmTestView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:vm="clr-namespace:MvvmTest.ViewModels" 
    WindowStartupLocation="CenterScreen" 
    Title="MvvmTestView" 
    Height="500" 
    Width="500"> 

    <Window.DataContext> 
     <vm:MvvmTestViewModel/> 
    </Window.DataContext> 
    <Grid> 
     <DockPanel> 
      <Menu> 
       <MenuItem Header="Menu"> 
        <MenuItem 
         Header="Tab01" 
         Command="{Binding SettingsViewCommand}" 
         CommandParameter="0"/> 
        <MenuItem 
         Header="Tab02" 
         Command="{Binding SettingsViewCommand}" 
         CommandParameter="1"/> 
       </MenuItem> 
      </Menu> 
     </DockPanel> 
     <DockPanel> 
      <Label Content="MainView" HorizontalAlignment="Center" VerticalAlignment="Center"/> 
     </DockPanel> 
    </Grid> 
</Window> 

SettingView.xaml

<Window x:Class="MvvmTest.Views.SettingsView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:tabData="clr-namespace:MvvmTest.Views" 
    xmlns:vm="clr-namespace:MvvmTest.ViewModels" 
    WindowStartupLocation="CenterScreen" 
    Title="SettingsView" 
    Height="400" 
    Width="400"> 

    <Window.DataContext> 
     <vm:MvvmTestViewModel/> 
    </Window.DataContext> 
    <Grid> 
     <TabControl 
      SelectedIndex="{Binding SettingsSelectedIndex, Mode=TwoWay}"> 
      <tabData:Tab01View/> 
      <tabData:Tab02View/> 
     </TabControl> 
    </Grid> 
</Window> 

SettingsViewModel.cs

using System.ComponentModel; 

namespace MvvmTest.ViewModels 
{ 
    public class SettingsViewModel : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

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

     private int _settingsSelectedIndex; 
     public int SettingsSelectedIndex 
     { 
      get 
      { 
       return _settingsSelectedIndex; 
      } 
      set 
      { 
       _settingsSelectedIndex = value; 
       OnPropertyChanged("SettingsSelectedIndex"); 
      } 
     } 
    } 
} 

MvvmTestViewModel.cs

using MvvmTest.Commands; 
using MvvmTest.Views; 
using System.ComponentModel; 
using System.Windows.Input; 

namespace MvvmTest.ViewModels 
{ 
    internal class MvvmTestViewModel : INotifyPropertyChanged 
    { 
     public event PropertyChangedEventHandler PropertyChanged; 

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

     private SettingsViewModel SettingsViewModel; 

     public MvvmTestViewModel() 
     { 
      SettingsViewModel = new SettingsViewModel(); 
      SettingsViewCommand = new SettingsViewCommand(this); 
     } 

     public ICommand SettingsViewCommand 
     { 
      get; 
      private set; 
     } 

     public void SettingsWindow() 
     { 
      SetIndex(); 
      SettingsView settingsView = new SettingsView() 
      { 
       DataContext = SettingsViewModel 
      }; 
      settingsView.ShowDialog(); 
     } 

     public int SetIndex() 
     { 
      SettingsViewModel.SettingsSelectedIndex = 1; 
      return SettingsViewModel.SettingsSelectedIndex; 
     } 
    } 
} 

SettingsViewCommand.cs

using MvvmTest.ViewModels; 
using System; 
using System.Windows.Input; 

namespace MvvmTest.Commands 
{ 
    internal class SettingsViewCommand : ICommand 
    { 
     private MvvmTestViewModel settingsViewModel; 

     public SettingsViewCommand(MvvmTestViewModel settingsViewModel) 
     { 
      this.settingsViewModel = settingsViewModel; 
     } 

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

     public bool CanExecute(object parameter) 
     { 
      return true; 
     } 

     public void Execute(object parameter) 
     { 
      settingsViewModel.SettingsWindow(); 
     } 
    } 
} 

答えて

1

私はSettingsViewCommand : ICommandのような複数のコマンドクラスを作成しないようにお勧めします。ビューから

internal class MvvmTestViewModel : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

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

    private SettingsViewModel SettingsViewModel; 

    public MvvmTestViewModel() 
    { 
     SettingsViewModel = new SettingsViewModel(); 
     SettingsViewCommand = new RelayCommand<int>(SettingsWindow); 
    } 

    public ICommand SettingsViewCommand 
    { 
     get; 
     private set; 
    } 

    public void SettingsWindow(int index) 
    { 
     SettingsViewModel.SettingsSelectedIndex = index; 
     SettingsView settingsView = new SettingsView() 
     { 
      DataContext = SettingsViewModel 
     }; 
     settingsView.ShowDialog(); 
    } 
} 

CommandParameterはSettingsWindowメソッドに渡されます。その代わり、このようなリファクタリングMvvmTestViewModelクラス、あなたのプロジェクトにMvvmFoundationを追加したと仮定すると(MvvmFoundation NuGetパッケージから例えばRelayCommand

をいくつかの汎用コマンドクラスを使用しますviewModelで選択されたインデックスを変更するために使用

+0

こんにちはASh、私もそれをしなければならないことを知っていましたが、一度に1ステップずつ取りたいと思っていました。とにかく、MVC FoundationのページのCodeplexから私のrelaycommand.csを入手しました。また、NuGetにMvvmFoundation.Wpfリファレンスを追加しました。今度はデバッガでエラーが発生しました...エラー\t CS0104 \t 'RelayCommand <>'は、 'MvvmTest.Commands.RelayCommand 'と26行目39のあいまいな参照です。\t私はここで間違っていますか? –

+0

@JoeyJoystick、プロジェクト内に2つのRelayCommand(Codeplexの "relaycommand.cs"とMvvmFoundation.WpfのRelayCommand)があるようです。そのうちの1つだけをプロジェクトに残してください。または、名前空間をコードファイルに追加しないでください( 'Using MvvmFoundation.Wpf;')。例えば、MvvmFoundation.Wpf.RelayCommand'フルクラス名を使用してください。 – ASh

+0

それは魅力的なように機能しています。そして、問題はあなたが上で説明したのとまったく同じでした。あなたにポイントを与えることを試みたが、私はまだそれらを渡すために十分なポイントを自分で持っていないと言われ続ける... –

関連する問題