18

複数の項目があるListBox(SelectionMode = Extended)があり、コンテキストメニュー機能を追加したいと思います。問題は、いくつかの条件に基づいてコンテキストメニューを動的に作成する方法です。例えば。1つの項目だけが選択されている場合は通常のコンテキストメニューを表示しますが、複数の項目が選択されている場合は他のコンテキストメニュー(たとえば、いくつかの新しい項目が追加されている)を表示したいと思います。さらに、選択した項目の中に、プロパティが設定されている項目が少なくとも1つある場合は、第3の種類のコンテキストメニューを作成したいと思います。など...このような複数の条件が存在する可能性があります。

基本的に、ユーザーがマウスボタンを右クリックした直後で、メニューが実際に表示される直前に、コンテキストメニューを動的に生成する必要があります。これは可能ですか?

4

3 に答える 3

13

これは古い質問だと思います。ContextMenuクラスはItemsSourceプロパティを介したバインディングをサポートしているため、MVVMシナリオでのOPの元の問題を解決する非常に簡単な答えがあるようです。

それが誰かがこれに遭遇するのを助けることを願っています。

XAML

      <ContextMenu ItemsSource="{Binding Path=ItemList, UpdateSourceTrigger=PropertyChanged}">
      </ContextMenu>

ViewModelでは、現在のアプリケーションの状態に応じて「ItemList」プロパティを動的に変更できます。

于 2014-04-24T18:56:45.643 に答える
8

私の質問に対する答えを見つけました。それはContextMenuOpeningイベントです。基本的に、このイベントを処理し、現在のアプリケーションの状態に応じてメニューを調整する必要があります。詳細はこちら:https ://msdn.microsoft.com/en-us/library/Bb613568(v = vs.100).aspx

于 2013-02-09T02:18:44.153 に答える
4

特定のシナリオに基づいて使用する事前定義されたコンテキストメニューのセットがある場合は、いつでもコンテキストメニューをリソースとして作成できます。

<Window.Resources>
    <ContextMenu x:Key="Menu1">
        <MenuItem>Item1</MenuItem>
    </ContextMenu>
    <ContextMenu x:Key="Menu2">
        <MenuItem>Item1</MenuItem>
        <MenuItem>Item2</MenuItem>
    </ContextMenu>
</Window.Resources>

次に、データトリガーを作成して、を使用するListBoxように設定します。ContextMenu以下で行ったことではなく、xamlで非常に乱雑になる可能性があるため、ビューモデルまたはコードビハインドのプロパティにバインドすることをお勧めします。ここでの実装は、1つの項目のみが選択されているかどうかを確認し、その場合はMenu1に切り替わります。

<ListBox x:Name="mylist" SelectionMode="Multiple" ContextMenu="{StaticResource Menu2}" >
    <ListBox.Style>
        <Style TargetType="{x:Type ListBox}">
            <Style.Triggers>
                <DataTrigger Binding="{Binding Path=SelectedItems.Count, RelativeSource={RelativeSource Self}}" Value="1" >
                    <Setter Property="ContextMenu" Value="{StaticResource ResourceKey=Menu1}" />
                </DataTrigger>
            </Style.Triggers>
        </Style>
    </ListBox.Style>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Path=DisplayName}" />
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

表示するコンテキストメニューの選択がビューのみに関係する場合は、コードビハインドで処理することをお勧めします。

public partial class MainWindow : Window
{
    public MainWindow()
    {
        // Hook up any events that might influence which menu to show
        mylist.SelectionChanged += listSelectionChanged;
        InitializeComponent();
    }

    private void listSelectionChanged(object sender, SelectionChangedEventArgs e)
    {
        var listBox = sender as ListBox;
        if (listBox == null)
            return; // Or throw something, hard

        ContextMenu menuToUse;
        // Logic for selecting which menu to use goes here

        listBox.ContextMenu = menuToUse;
    }
}

ViewModelがどのメニューを表示するかに関心がある場合(そのようには聞こえませんが、完全なコンテキストを知らなければ見分けるのは難しいです)、ViewModelで表示するメニューを決定できるいくつかのプロパティを公開できますContextMenu。個々のブール値プロパティではなく、常に1つのブール値のみが真であることを確認するクラスを作成することをお勧めします。

public class MyViewModel : INotifyPropertyChanged
{

    public MyViewModel()
    {
        SelectedItems = new ObservableCollection<string>();
        SelectedItems.CollectionChanged += SelectedItemsChanged;
    }

    private void SelectedItemsChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        // Logic to see which ShowMenuX property to set to true goes here
    }

    public ObservableCollection<string> SelectedItems { get; set; }

    private bool _showMenu1 = false;
    public bool ShowMenu1
    {
        get { return _showMenu1; }
        set
        {
            _showMenu1 = value;
            RaisePropertyChanged("ShowMenu1");
        }
    }

    // INotifyPropertyChanged implementation goes here
}
于 2013-02-09T02:04:03.770 に答える