4

リストビューでコンテキスト メニューを使用して、元のアイテムのデータを必要とするコードを実行しようとしています。

私は最初にこれをしました:

XAML:

    <ListView x:Name="lvResources" ScrollViewer.VerticalScrollBarVisibility="Visible">
      <ListView.Resources>
        <ContextMenu x:Key="resourceContextMenu">
            <MenuItem Header="Get Metadata" Name="cmMetadata" Click="cmMetadata_Click" />
        </ContextMenu>
      </ListView.Resources>
      <ListView.ItemContainerStyle>
          <Style TargetType="{x:Type ListViewItem}">
              <Setter Property="ContextMenu" Value="{StaticResource resourceContextMenu}" />
          </Style>
      </ListView.ItemContainerStyle>
 ...

C#:

    private void cmMetadata_Click(object sender, RoutedEventArgs e)
    {
      // code that needs item data here
    }

しかし、元のリストビュー項目にはそのようにアクセスできないことがわかりました.

MouseDown イベントをインターセプトし、クリックされた listviewitem にプライベート フィールドを設定するなど、これを回避する方法についていくつかの戦術を読みましたが、その周りにデータを渡すのは少しハッキリしているように見えるので、うまくいきません。仕方。WPF は簡単なはずですよね?:) 私はこのSO の質問と このMSDN フォーラムの質問を読みましたが、私の場合はどちらの記事も機能していないように見えるため、実際にこれを行う方法はまだわかりません。クリックされた項目をコンテキスト メニューに渡すより良い方法はありますか?

ありがとう!

4

3 に答える 3

4

チャーリーの答えに似ていますが、XAML の変更は必要ありません。

private void cmMetadata_Click(object sender, RoutedEventArgs e)
{
    MenuItem menu = sender as MenuItem;
    ListViewItem lvi = lvResources.ItemContainerGenerator.ContainerFromItem(menu.DataContext) as ListViewItem;
}
于 2009-07-15T04:03:55.037 に答える
1

そこで、コマンド ソリューションを試して実装することにしました。私は今それがどのように機能しているかにとても満足しています.

まず、私のコマンドを作成しました:

public static class CustomCommands
{
    public static RoutedCommand DisplayMetadata = new RoutedCommand();
}

次に、カスタム リストビュー コントロールで、コンストラクターにバインドする新しいコマンドを追加しました。

public SortableListView()
{
    CommandBindings.Add(new CommandBinding(CustomCommands.DisplayMetadata, DisplayMetadataExecuted, DisplayMetadataCanExecute));
}

また、イベント ハンドラを追加しました。

public void DisplayMetadataExecuted(object sender, ExecutedRoutedEventArgs e)
{
    var nbSelectedItem = (MyItem)e.Parameter;

    // do stuff with selected item
}

public void DisplayMetadataCanExecute(object sender, CanExecuteRoutedEventArgs e)
{
    e.CanExecute = true;
    e.Handled = true;
}

既にスタイル セレクターを使用してスタイルをリストビュー項目に動的に割り当てていたので、xaml でこれを行う代わりに、コード ビハインドでバインディングを設定する必要があります。ただし、xaml でも同様に実行できます。

public override Style SelectStyle(object item, DependencyObject container)
{
    ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(container);
    MyItem selectedItem = (MyItem)item;
    Style s = new Style();

    var listMenuItems = new List<MenuItem>();
    var mi = new MenuItem();
    mi.Header= "Get Metadata";
    mi.Name= "cmMetadata";
    mi.Command = CustomCommands.DisplayMetadata;
    mi.CommandParameter = selectedItem;
    listMenuItems.Add(mi);

    ContextMenu cm = new ContextMenu();
    cm.ItemsSource = listMenuItems;

    // Global styles
    s.Setters.Add(new Setter(Control.ContextMenuProperty, cm));

    // other style selection code

    return s;
}

マウス クリックでフィールドを設定し、その方法でクリックされたものにアクセスしようとするよりも、このソリューションの感触がはるかに優れています。

于 2009-07-14T20:46:24.027 に答える