2016-11-07 5 views
1

私はWPFとMVVMを初めて使いました。私は、クロム、IE、メモ帳などのさまざまなアプリケーションを起動する複数のボタンがあるクリーンなプロジェクト構造を持つ方法を整理しようとしています。複数のボタンに対して1つのViewModelを持つことは可能ですか?複数のボタンの1つのビューモデル

hereのコードを使用して開始しました。解決策として、そのリンクからビューモデルベースのコードを作成し、そのベースを拡張する各ボタンの他​​のビューモデルを用意しました。

それぞれが独特のアクションがあります。

public override void ClickAction() 
    { 
     Process ieProcess = new Process(); 
     ieProcess.StartInfo.FileName = "IExplore.exe"; 
     ieProcess.Start(); 
    } 

しかし、私はこれをやって行くための正しい方法がわかりませんよ。このアプローチでDataContextを作成するにはどうすればよいですか?どんな助けもありがとうございます。

+1

なぜ、各ボタンには独自のデータコンテキストがありますか?あなたがアイテムコントロールにいない限り、それは正しいとは言えません。 – BradleyDotNET

+0

お返事ありがとうございます。私が言ったように、私はこれには新しく、デザインパターンを掴むのに苦労しています。あなたは私が違ったやり方で何をすべきか/これにアプローチする方法を提案できますか? –

+0

2つの提案、実際には:) – BradleyDotNET

答えて

5

ビューごとに1つのビューモデルが必要です。ビュー内のアイテムごとではありません(この場合はボタン)。あなたが記述しているものを行う簡単な方法は、あなたのexeファイル名を渡すCommmandParameterプロパティを使用することです:あなたのコマンドで

<Button Content="Launch IE" Command="{Binding LaunchAppCommand}" CommandParameter="IExplorer.exe"/> 
<Button Content="Launch Notepad" Command="{Binding LaunchAppCommand}" CommandParameter="notepad.exe"/> 
<Button Content="Launch Chrome" Command="{Binding LaunchAppCommand}" CommandParameter="chrome.exe"/> 

public ICommand LaunchAppComand {get; private set;} 
... 
public MyViewModel() 
{ 
    LaunchAppCommand = new DelegateCommand(LaunchApp); 
} 
... 
private void LaunchApp(object parameter) 
{ 
    string processName = (string)parameter; 
    Process launchProc = new Process(); 
    launchProc.StartInfo.FileName = processName; 
    launchProc.Start(); 
} 

ハードあなたはできるすべてのボタンをコーディングないようにするにはItemsControlを使用します。ItemsControlは、作成するテンプレートごとに個別のデータコンテキストを設定します。 ItemsControlは、あなたが得るために結合ElementNameを必要とするバインドされた項目にテンプレート内DataContextを設定するので

//ProcessShortcut.cs 
public class ProcessShortcut 
{ 
    public string DisplayName {get; set;} 
    public string ProcessName {get; set;} 
} 

//MyViewModel.cs, include the previous code 

//INotifyPropertyChanged left out for brevity 
public IEnumerable<ProcessShortcut> Shortcuts {get; set;} 

public MyViewModel() 
{ 
    Shortcuts = new List<ProcessShortcut>() 
    { 
     new ProcessShortcut(){DisplayName = "IE", ProcessName="IExplorer.exe"}, 
     new ProcessShortcut(){DisplayName = "Notepad", ProcessName="notepad.exe"}, 
     new ProcessShortcut(){DisplayName = "Chrome", ProcessName="chrome.exe"}, 
    }; 
} 

//MyView.xaml 
<Window x:Name="Root"> 
... 
    <ItemsControl ItemsSource="{Binding Shortcuts}"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Button Content="{Binding DisplayName, StringFormat='{}Start {0}'}" 
         Command="{Binding ElementName=Root, Path=DataContext.LaunchAppCommand}" 
         CommandParameter="{Binding ProcessName}"/> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
... 
</Window> 

:そのためには、データクラスのコレクション、そしてあなたのコマンドに取得するには、わずかに異なる方法が必要ですコマンドには、ProcessShortcutのメンバーへのアクセス権を取得する必要はありません。長期的には、これはあなたがこのような反復的なコントロールを持っているときに取っておきたいアプローチです。

+0

ご協力いただきありがとうございます。間違いなく私の学習プロセスの説明と始まりです!私はDelegateCommandの実装が十分だと思っていましたが、これについての助言やアドバイスはありますか?それはMicrosoftのそれの実装されていないようです。 –

+0

@AlexRosenfeldオンライン実装は一般的に大丈夫です。 'CanExecuteChanged'の実装は、CommandManager.RequerySuggested(http://stackoverflow.com/a/3408591/1783619参照)を使用すると非常に非効率です。限り、それらのほとんどが良いことを避ける限り – BradleyDotNET

+0

さて、もう一度ありがとう!現在のところ、クリックコマンドのバインディングに問題がありますが、LaunchAppCommand呼び出しのいずれも起動していません。私はしばらくそれを見て、私がそれを得ることができない場合は後でフォローアップを投稿します。あなたはとても役に立ちました –

関連する問題