質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

89.10%

[WPF]UserControlのContextMenuを外部から変更したい

解決済

回答 1

投稿

  • 評価
  • クリップ 0
  • VIEW 2,050

mt-

score 13

いつもお世話になります。

前提・実現したいこと

WPFのユーザーコントロール内の一部(ContextMenu)を
ユーザーコントロールの使用元から変更したいのですが、
上記実現する方法が不明なので質問させていただきました。

環境

Visual Studio 2017
C# 4.6.1
WPF
MVVM Lightフレームワーク使用

現状のソースコード

具体的には、下記のようなXamlコードがあり。。。

MainWindow.xaml

<Window x:Class="WpfUserControlTest.View.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfUserControlTest.View"
        mc:Ignorable="d"
        DataContext="{Binding MainWindow, Source={StaticResource Locator}}"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <local:CustomListBox Grid.Column="0" Background="AliceBlue" DataContext="{Binding CustomListVM, Source={StaticResource Locator}}" />
        <local:CustomListBox Grid.Column="1" Background="Aqua" DataContext="{Binding CustomListVM2, Source={StaticResource Locator}}" />

    </Grid>
</Window>

CustomListBox.xaml

<UserControl x:Class="WpfUserControlTest.View.CustomListBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfUserControlTest.View"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>

        <ListBox x:Name="_list"
                 Background="{Binding Background, RelativeSource={RelativeSource FindAncestor ,AncestorType={x:Type UserControl}}}"
                 SelectedItem="{Binding SelectedItem}"
                 ItemsSource="{Binding List}" >
            <ListBox.ItemTemplate>
                <DataTemplate >
                    <ContentControl>

                        <!-- アイテムパネル -->
                        <StackPanel Orientation="Vertical" Background="Transparent" Tag="{Binding Path=DataContext , ElementName=_list}" >
                            <TextBlock Text="{Binding Title}" />
                            <TextBlock Text="{Binding Data}" />
                            <StackPanel.ContextMenu>
                                <ContextMenu>
                                    <MenuItem Header="削除"
                                              CommandParameter="{Binding }" 
                                              Command="{Binding PlacementTarget.Tag.AssetDeleteCommand , RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}" 
                                              />
                                </ContextMenu>
                                <!--
                                <ContextMenu>
                                    <MenuItem Header="編集"
                                              CommandParameter="{Binding }" 
                                              Command="{Binding PlacementTarget.Tag.AssetEditCommand , RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}" 
                                              />
                                </ContextMenu>
                                -->
                            </StackPanel.ContextMenu>
                        </StackPanel>

                    </ContentControl>
                </DataTemplate>
            </ListBox.ItemTemplate>
        </ListBox>
    </Grid>
</UserControl>

上記コードだとListBoxのアイテムを右クリックすると削除項目のみのコンテキストメニューが表示します。

しかしながらこの削除項目が場合によっては編集項目となったり、
「編集」「削除」「開く」が選択できるコンテキストメニューになったりと場合によってコンテキストメニューが変わります

具体的にやりたいコード

最終的にはユーザーコントロールの使用元から下記のように
コンテキストメニューを変更したいです。

MainWindow.xaml

<Window x:Class="WpfUserControlTest.View.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfUserControlTest.View"
        mc:Ignorable="d"
        DataContext="{Binding MainWindow, Source={StaticResource Locator}}"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*" />
            <ColumnDefinition Width="*" />
        </Grid.ColumnDefinitions>

        <local:CustomListBox Grid.Column="0" Background="AliceBlue" DataContext="{Binding CustomListVM, Source={StaticResource Locator}}" >
             <!-- このようにコンテキストメニューを下記のように指定したい -->
            <ContextMenu>
                <MenuItem Header="削除"
                    CommandParameter="{Binding }" 
                    Command="{Binding PlacementTarget.Tag.AssetDeleteCommand , RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}" />
            </ContextMenu>
        </local:CustomListBox>
    </Grid>
</Window>

上記のような方法以外でもユーザーコントロール外からユーザーコントロール内部のコンテキストメニューの変更方法等ご存知であればご教示の程よろしくお願いいたします。

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

回答 1

checkベストアンサー

+1

メニューにデータをバインドし、メニュー自体を編集するのではなく、データを編集してください。

MenuItemをバインド /WPF

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2018/12/05 19:16

    ご回答ありがとうございます。

    すみませんリンク先の内容を見てみたのですが、
    具体的にどのようにすればContextMenuのMenu内容が増やせるのかわかりませんでした。
    恐らく「ContextMenu」に対してコレクションをバインドし、
    コレクション内の要素のMenuItemとして表示できるという解釈をしたのですが、具体的にどのようにすればよいかリンク先のコードから判断がつきませんでした。。。

    実際に下記は試してみましたがうまくいかずといったところです。
    [試してみたこと]
    上記質問に記載したCustomListBox.xamlのCustomListBoxのコンテキストメニューに対して下記のように設定してみました。
    ・ContextMenuのDataContextに
     DataContext="{Binding PlacementTarget.Tag.List , RelativeSource={RelativeSource Self}}"
     という仮のリストを設定(中身はTitleとDataという文字列型のプロパティをもったインスタンスのコレクションで 内容は{"Title1" , "Data1" } , {"Title2" , "Data2"})が入っています。

    これでコンテキストメニューのメニューの表記がListのコレクション内容である2行になるのかと思ったのですが、MenuItemは1つのままでした。

    もう少し詳細な方法があればご教示いただけますと幸いです。

    ※メニューアイテムのヘッダーは下記のように設定したところ、
     無事コレクションの1件目のタイトルである "Title1"が表示できました。
     <MenuItem Header="{Binding Title}"

    キャンセル

  • 2018/12/05 19:24

    サンプルの通り ItemsSource を使わなければなりませんよ。

    キャンセル

  • 2018/12/05 21:00

    速いレスポンスで回答していただきありがとうございます。

    頂いた情報から下記のようにXamlを設定することで解決できました。
    <ContextMenu
    ItemsSource="{Binding PlacementTarget.Tag.List , RelativeSource={RelativeSource Self}}"
    x:Name="_Menu" >

    <ContextMenu.ItemContainerStyle>
    <Style TargetType="{x:Type MenuItem}">
    <Setter Property="Header" Value="{Binding Title}" />
    </Style>
    </ContextMenu.ItemContainerStyle>
    </ContextMenu>

    後は上記対してコマンドやコマンドパラメータを設定していこうと思います。
    本当にありがとうございました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 89.10%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる