31

MVVMの学習を始めたばかりです。このMVVM チュートリアルに従ってアプリケーションをゼロから作成しました(すべての MVVM 初心者に強くお勧めします)。基本的に、これまでに作成したのは、ユーザーがデータを追加するいくつかのテキスト ボックスと、そのデータを保存するためのボタンです。これにより、作成されたすべてのエントリが ListBox に取り込まれます。

ここで行き詰まりました。ListBoxItem をダブルクリックして、作成して ViewModel に追加したコマンドをトリガーできるようにしたいのです。XAML 側を終了する方法がわかりません。つまり、そのコマンドを ListBox(Item) にバインドする方法がわかりません。

XAML は次のとおりです。

...
<ListBox 
    Name="EntriesListBox" 
    Width="228" 
    Height="208" 
    Margin="138,12,0,0" 
    HorizontalAlignment="Left" 
    VerticalAlignment="Top" 
    ItemsSource="{Binding Entries}" />
...

ビューモデルは次のとおりです。

public class MainWindowViewModel : DependencyObject
{
    ...
    public IEntriesProvider Entries
    {
        get { return entries; }
    }

    private IEntriesProvider entries;
    public OpenEntryCommand OpenEntryCmd { get; set; }

    public MainWindowViewModel(IEntriesProvider source)
    {
        this.entries = source;
        ...
        this.OpenEntryCmd = new OpenEntryCommand(this);
    }
    ...
}

最後に、ユーザーが EntriesListBox 内の項目をダブルクリックしたときに実行する OpenEntryCommand を次に示します。

public class OpenEntryCommand : ICommand
{
    private MainWindowViewModel viewModel;

    public OpenEntryCommand(MainWindowViewModel viewModel)
    {
        this.viewModel = viewModel;
    }

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

    public bool CanExecute(object parameter)
    {
        return parameter is Entry;
    }

    public void Execute(object parameter)
    {
        string messageFormat = "Subject: {0}\nStart: {1}\nEnd: {2}";
        Entry entry = parameter as Entry;
        string message = string.Format(messageFormat, 
                                       entry.Subject, 
                                       entry.StartDate.ToShortDateString(), 
                                       entry.EndDate.ToShortDateString());

        MessageBox.Show(message, "Appointment");
    }
}

助けてください、よろしくお願いします。

4

6 に答える 6

69

残念ながら、ButtonBase派生コントロールのみがICommandオブジェクトをCommandプロパティにバインドする可能性があります (Clickイベント用)。

ただし、Blend が提供する API を使用して、イベント (の場合MouseDoubleClickのようにListBox) をICommandオブジェクトにマップできます。

<ListBox>
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="MouseDoubleClick">
            <i:InvokeCommandAction Command="{Binding YourCommand}"/>
        </i:EventTrigger>
    </i:Interaction.Triggers>
</ListBox>

を定義する必要がxmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"あり、 への参照が必要System.Windows.Interactivity.dllです。

-- 編集 -- これは WPF4 の一部ですが、WPF4 を使用していない場合は Microsoft.Windows.Interactivity を使用できます。この dll は、Blend を必要としない Blend SDK からのものです

更新:あなたに役立つものを見つけました。これを行う方法のウォークスルーと、必要なライブラリへのリンクが含まれているMVVM Light Toolkit のこのリンクを確認してください。MVVM Light Toolkit は、MVVM を Silverlight、WPF、および WP7 に適用するための非常に興味深いフレームワークです。

お役に立てれば :)

于 2011-04-04T23:09:53.067 に答える
9

これは、DoubleClick イベントのためにややこしくなります。これを行うにはいくつかの方法があります。

  1. コード ビハインドでダブルクリック イベントを処理し、ビューモデルでコマンド/メソッドを手動で呼び出す
  2. 添付された動作を使用して、DoubleClick イベントを Command にルーティングします
  3. ブレンド動作を使用して、DoubleClick イベントをコマンドにマップします

2 と 3 の方が純粋かもしれませんが、率直に言って、1 の方が簡単で、それほど複雑ではありません。1 回限りのケースでは、おそらくアプローチ #1 を使用します。

ここで、たとえば各項目にハイパーリンクを使用するように要件を変更すると、より簡単になります。XAML でルート要素に名前を付けることから始めます (たとえば、ウィンドウの場合)。

<Window .... Name="This">

ここで、ListBox アイテムの DataTemplate で、次のようなものを使用します。

<ListBox ...>
  <ListBox.ItemTemplate>
    <DataTemplate>
      <Hyperlink 
        Command="{Binding ElementName=This, Path=DataContext.OpenEntryCmd}"
        Text="{Binding Path=Name}" 
        />

ElementName バインディングを使用すると、特定のデータ項目ではなく、ViewModel のコンテキストから OpenEntryCmd を解決できます。

于 2011-04-04T23:02:30.650 に答える