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

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

新規登録して質問してみよう
ただいま回答率
85.48%
MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

Q&A

解決済

2回答

5223閲覧

[WPF][MVVM] ToggleButtonを押した時ContextMenuを表示したい

Base

総合スコア28

MVVM

MVVM(Model View ViewModel)は構築上のデザインパターンで、表現ロジック(ViewModel)によってデータ(Model)からページ(View)を分離させます。

WPF

Windows Presentation Foundation (WPF) は、魅力的な外観のユーザー エクスペリエンスを持つ Windows クライアント アプリケーションを作成するための次世代プレゼンテーション システムです

0グッド

0クリップ

投稿2019/04/14 06:10

編集2019/04/16 05:30

前提・実現したいこと

こんばんは。
WPF + Visual Studio2015にてトグルボタンのメニューを作成中です。

トグルボタンを押した時に、展開してメニューが表示するようにしたいです。
今は、押しても何もメニューが展開されない状態です。
ViewModelでの、フラグの切り替えは出来ていますが、ContextMenuを展開するのにはどうしたら良いのかを調べています。

色々調べましたが、情報を探し出せなかった為、ご教授頂けますと幸いです。

発生している問題・エラーメッセージ

ContextMenuのIsOpenが認識されない状態で、メニューが開かない状態。

該当のソースコード

xmal

1 <Window.Resources> 2 <local:BindingProxy x:Key="Proxy" Data="{Binding}" /> 3 </Window.Resources> 4 5<Grid> 6 <StackPanel> 7 <Menu x:Name="menu" HorizontalAlignment="Left" Height="24" VerticalAlignment="Top" Width="519" Margin="0,0,-0.333,0"> 8 <MenuItem Header="ファイル"> 9 </MenuItem> 10 </Menu> 11 </StackPanel> 12 <StackPanel> 13 <ToolBar Margin="0,20,-0.333,0" Height="30"> 14 <ToggleButton IsChecked="{Binding ShowMeoDataOnly, Mode=TwoWay}"> 15 <ToggleButton.ContextMenu> 16 <ContextMenu DataContext="{StaticResource Proxy}" IsOpen="{Binding Data.ShowMeoDataOnly, Mode=TwoWay}"> 17 <MenuItem Command="{Binding Source={StaticResource Proxy}, Path=Data.MyCommand}"> 18 <MenuItem.Header> 19 <TextBlock Text="実行可能状態にする"/> 20 </MenuItem.Header> 21 </MenuItem> 22 <MenuItem Command="{Binding Source={StaticResource Proxy}, Path=Data.MyCommand}"> 23 <MenuItem.Header> 24 <TextBlock Text="移動する"/> 25 </MenuItem.Header> 26 </MenuItem> 27 <MenuItem Command="{Binding Source={StaticResource Proxy}, Path=Data.MyCommand}"> 28 <MenuItem.Header> 29 <TextBlock Text="ファイルから呼び出す"/> 30 </MenuItem.Header> 31 </MenuItem> 32 </ContextMenu> 33 34 </ToggleButton.ContextMenu> 35 <WrapPanel> 36 <StackPanel> 37 <TextBlock Text="操作内容" VerticalAlignment="Center" /> 38 </StackPanel> 39 <!--<Path Width="10" Height="5" Stretch="Fill" Fill="Black" Data="F1 M0,0 L10,0 L5,10 Z " />--> 40 <Border Width="8" /> 41 </WrapPanel> 42 43 </ToggleButton> 44 </ToolBar> 45 46 </StackPanel> 47 </Grid> 48

MainWindowViewModel

1 2 private bool _ShowMeoDataOnly = false; 3 public bool ShowMeoDataOnly 4 { 5 get 6 { 7 Console.WriteLine("Get Show Me Data >>" + _ShowMeoDataOnly); 8 return _ShowMeoDataOnly; 9 } 10 set 11 { 12 if( _ShowMeoDataOnly != value) 13 { 14 _ShowMeoDataOnly = value; 15 16 if(_ShowMeoDataOnly == true) 17 { 18 Console.WriteLine("Set Show Me Data >> Open "); 19 20 } 21 22 base.RaisePropertyChanged(() => ShowMeoDataOnly); 23 } 24 } 25 } 26

BindingProxy

1 2using System.Windows; 3 4// BindingProxy.csを作成 5 6 public class BindingProxy : Freezable 7 { 8 protected override Freezable CreateInstanceCore() 9 { 10 return new BindingProxy(); 11 } 12 13 public object Data 14 { 15 get { return (object)GetValue(DataProperty); } 16 set { SetValue(DataProperty, value); } 17 } 18 19 public static readonly DependencyProperty DataProperty = 20 DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new UIPropertyMetadata(null)); 21 }

試したこと

1)原因は、下記のURLに乗っている事だというところまでは突き止めたが、
MVVM的にどうすれば良いか分からなかった。

https://social.msdn.microsoft.com/Forums/ja-JP/48ee254e-ac36-4fac-8df6-cbca000d19a6/contextmenu12434isopen1239138283123671239212467125101253112489123642?forum=wpfja

2)オリジナルで作る必要があるかと思い、下記を参考にしよう考えたが、
controls:CustomContextMenu の部分がどこからきているか、理解できなかった。

https://stackoverflow.com/questions/33688346/dynamically-create-contextmenu/33731677#33731677

よろしくお願いいたします。

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

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

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

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Zuishin

2019/04/14 11:38

・どのような手順を取るとどうなるようにしたいのか ・今はどうなるのか の二点についてわかりやすい説明があれば回答がつくかもしれません。 その際、「認識」「反応」「うまくいかない」などの抽象的でわかりにくい言葉は避けてください。
Base

2019/04/14 23:57

ありがとうございます。 修正させて頂きました。 よろしくお願いいたします。
Zuishin

2019/04/14 23:58

・どのような手順を取るとどうなるようにしたいのか ・今はどうなるのか の二点についてわかりやすい説明
Zuishin

2019/04/14 23:58

があれば回答がつくかもしれません。 長文すみませんでした。読みやすいように分けました。
guest

回答2

0

ベストアンサー

PlacementTargetはDependencyPropertyなのでBindできますよ。

<ContextMenu IsOpen="{Binding ShowMeoDataOnly, Mode=TwoWay}" PlacementTarget="{Binding RelativeSource={RelativeSource AncestorType=ToggleButton}}">

上記で、"一度右クリックで表示した後は"表示されるようになります。
一度右クリックで開かなくてはいけない理由と対策はこちらに書いてあります。ContextMenuをViewModelから開く方法

ちなみに、ShowMeoDataOnlyが両方TwoWayだとポップアップが閉じた時にToggleButtonまでoffになってしまうのですが、これは意図した動き(Menuのようにポップアップ開いている時だけ色を変えたい?)ですか?


昨日は上記だけでできていた気がしたのですが、今やってみたらできなくなっていました。なんでだろ。。。
Bindエラーが出ていてうまくBind出来ていないようなので、こちらにもBindingProxyを使ってやればよいと思います。

<ContextMenu DataContext="{StaticResource Proxy}" IsOpen="{Binding Data.ShowMeoDataOnly, Mode=TwoWay}">

投稿2019/04/15 00:56

編集2019/04/16 04:10
moredeep

総合スコア1507

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Base

2019/04/16 02:51

ありがとうございます。 頂いた情報通りにコードを更新し見ました(上記コードを更新) しかし、、右クリックしないと動作しない状況です。。 何か・・・自分のコードに問題があるのでしょうか・・・。 ポップアップが閉じた時にToggleButtonまでoffになってしまう  → これは意図した動きになっています。
Base

2019/04/16 05:37 編集

ありがとうございました。 動作確認取れました。 質問した際のソースコードが、最終動作コードになんります。
guest

0

これってようするに、ToggleButtonがOnの間はContextMenuを開いた
ままにしておくってことですかね?
だとしたらIsOpenで制御するのは無理があるように思います。

素直にPopupにしたほうが良いのでは?

Xaml

1<Grid> 2 <StackPanel> 3 <Menu x:Name="menu" HorizontalAlignment="Left" Height="24" VerticalAlignment="Top" Width="519" Margin="0,0,-0.333,0"> 4 <MenuItem Header="ファイル"> 5 </MenuItem> 6 </Menu> 7 </StackPanel> 8 <StackPanel> 9 <ToolBar Margin="0,20,-0.333,0" Height="30"> 10 <ToggleButton IsChecked="{Binding ShowMeoDataOnly, Mode=TwoWay}"> 11 <!--<ToggleButton.ContextMenu> 12 <ContextMenu IsOpen="{Binding ShowMeoDataOnly, Mode=TwoWay}"> 13 <MenuItem> 14 <MenuItem.Header> 15 <TextBlock Text="実行可能状態にする"/> 16 </MenuItem.Header> 17 </MenuItem> 18 <MenuItem> 19 <MenuItem.Header> 20 <TextBlock Text="移動する"/> 21 </MenuItem.Header> 22 </MenuItem> 23 <MenuItem> 24 <MenuItem.Header> 25 <TextBlock Text="ファイルから呼び出す"/> 26 </MenuItem.Header> 27 </MenuItem> 28 </ContextMenu> 29 30 </ToggleButton.ContextMenu>--> 31 <WrapPanel> 32 <StackPanel> 33 <TextBlock Text="操作内容" VerticalAlignment="Center" /> 34 </StackPanel> 35 <Border Width="8" /> 36 </WrapPanel> 37 38 </ToggleButton> 39 </ToolBar> 40 41 <Popup IsOpen="{Binding ShowMeoDataOnly, Mode=TwoWay}" Placement="MousePoint"> 42 <Border> 43 <StackPanel Orientation="Vertical"> 44 <MenuItem> 45 <MenuItem.Header> 46 <TextBlock Text="実行可能状態にする"/> 47 </MenuItem.Header> 48 </MenuItem> 49 <MenuItem> 50 <MenuItem.Header> 51 <TextBlock Text="移動する"/> 52 </MenuItem.Header> 53 </MenuItem> 54 <MenuItem> 55 <MenuItem.Header> 56 <TextBlock Text="ファイルから呼び出す"/> 57 </MenuItem.Header> 58 </MenuItem> 59 </StackPanel> 60 </Border> 61 </Popup> 62 63 </StackPanel> 64</Grid>

投稿2019/04/15 00:08

ebiryo

総合スコア797

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Base

2019/04/16 05:32

ありがとうございます。 もう一つの実現方法として、参考にさせて頂きました。 今回は、自分のやりたい事にどんぴしゃだった、moredeep様の回答をベストアンサーに選ばせて頂きました。 ご回答いただき、ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問