WPFのイヤなところなのですが、ContextMenu
はVisualTree
が繋がっておらず単純にはFindAncestor
が効きません。
PlacementTarget
とTag
の組み合わせ
BindingProxy
の2つがよくある解決法です。
xml
1 < Window
2 x: Class = " Questions296143.MainWindow "
3 xmlns = " http://schemas.microsoft.com/winfx/2006/xaml/presentation "
4 xmlns: x = " http://schemas.microsoft.com/winfx/2006/xaml "
5 xmlns: local = " clr-namespace:Questions296143 "
6 Width = " 800 "
7 Height = " 450 " >
8 < Window.DataContext >
9 < local: MainVM />
10 </ Window.DataContext >
11 < Window.Resources >
12 < local: BindingProxy x: Key = " proxy " Data = " {Binding} " />
13 </ Window.Resources >
14 < Grid >
15 < ListBox ItemsSource = " {Binding MyList} " >
16 < ListBox.ItemTemplate >
17 < DataTemplate >
18 < UniformGrid Rows = " 1 " >
19
20 < GroupBox Header = " Original " >
21 < Button Content = " {Binding DataContext.Fiz, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}} " >
22 < Button.ContextMenu >
23 < ContextMenu >
24 < MenuItem Header = " {Binding DataContext.Biz, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}} " />
25 </ ContextMenu >
26 </ Button.ContextMenu >
27 </ Button >
28 </ GroupBox >
29
30 <!-- Tag xamlのみで済むが、パット見何してるかわかりにくい -->
31 < GroupBox Header = " Tag " >
32 < Button
33 Content = " {Binding DataContext.Fiz, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}} "
34 Tag = " {Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}} " >
35 < Button.ContextMenu >
36 < ContextMenu >
37 < MenuItem Header = " {Binding PlacementTarget.Tag.Biz, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}} " />
38 </ ContextMenu >
39
40 <!-- あるいは -->
41 <!--<ContextMenu DataContext="{Binding PlacementTarget.Tag, RelativeSource={RelativeSource Self}}">
42 <MenuItem Header="{Binding Biz}" />
43 </ContextMenu>-->
44 </ Button.ContextMenu >
45 </ Button >
46 </ GroupBox >
47
48 <!-- BindingProxy C#コードが必要だが、xamlはスッキリ -->
49 < GroupBox Header = " BindingProxy " >
50 < Button Content = " {Binding DataContext.Fiz, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}} " >
51 < Button.ContextMenu >
52 < ContextMenu >
53 < MenuItem Header = " {Binding Data.Biz, Source={StaticResource proxy}} " />
54 </ ContextMenu >
55 </ Button.ContextMenu >
56 </ Button >
57 </ GroupBox >
58
59 <!-- AncestorLevelとかの話ではない。ツリーが繋がってないので出るわけがない! -->
60 < GroupBox Header = " takapi__cs " >
61 < Button Content = " {Binding DataContext.Fiz, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}} " >
62 < Button.ContextMenu >
63 < ContextMenu >
64 < MenuItem Header = " {Binding DataContext.Biz, RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType=Window}} " />
65 </ ContextMenu >
66 </ Button.ContextMenu >
67 </ Button >
68 </ GroupBox >
69 </ UniformGrid >
70 </ DataTemplate >
71 </ ListBox.ItemTemplate >
72 </ ListBox >
73 </ Grid >
74 </ Window >
cs
1 using System . Collections . Generic ;
2 using System . Windows ;
3
4 namespace Questions296143
5 {
6 class BindingProxy : Freezable
7 {
8 public object Data { get => GetValue ( DataProperty ) ; set => SetValue ( DataProperty , value ) ; }
9 public static readonly DependencyProperty DataProperty
10 = DependencyProperty . Register ( nameof ( Data ) , typeof ( object ) , typeof ( BindingProxy ) ,
11 new PropertyMetadata ( null ) ) ;
12
13 protected override Freezable CreateInstanceCore ( ) => new BindingProxy ( ) ;
14 }
15
16 class MainVM
17 {
18 public string Biz { get ; } = "Biz" ;
19 public string Fiz { get ; } = "Fiz" ;
20 public List < string > MyList { get ; } = new List < string > { "hoge" } ;
21 }
22
23 public partial class MainWindow : Window
24 {
25 public MainWindow ( ) => InitializeComponent ( ) ;
26 }
27 }
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2020/10/06 09:24