Reputation: 355
When contextmenu is opening, I want to fill a textbox with source control's information, for example its name and so on, for viewing and editing purpose.
But I however cannot access the opening contextmenu anyway. Maybe this is because my less understanding of control's xaml style.
The following is my xaml:
the context menu part: I want to fill the TextBox when contextmenu is opening.
<ContextMenu x:Key="VacUnitContextMenu" >
<MenuItem Header="Property">
<MenuItem>
<MenuItem.Header>
<StackPanel Orientation="Horizontal">
<Label Content="Name" />
<TextBox Width="60" Name="VacName" Margin="2,0" />
</StackPanel>
</MenuItem.Header>
</MenuItem>
<MenuItem Header="Get" Command="{x:Static s:DesignerCanvas.VacUnitNameGet}"/>
</MenuItem>
<MenuItem Header="X">
<MenuItem Header="TEST" Command="{x:Static s:DesignerCanvas.XTest}">
<MenuItem.Icon>
<Image Source="Images/SendToBack.png" Width="16"/>
</MenuItem.Icon>
</MenuItem>
</MenuItem>
</ContextMenu>
the context menu is used in this way:
<!-- VacUnit Style -->
<Style TargetType="{x:Type s:VacUnit}" >
<Setter Property="MinWidth" Value="10"/>
<Setter Property="MinHeight" Value="10"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type s:VacUnit}">
<Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}"
ContextMenu="{StaticResource VacUnitContextMenu}"
>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
I use conextmenuopening event, and try to fill the textbox there, How to: Handle the ContextMenuOpening Event
But I cannnot get the contextmenu, it is null:
FrameworkElement fe = e.Source as FrameworkElement;
ContextMenu cm = fe.ContextMenu;
Many thanks in advance.
Ting
Upvotes: 0
Views: 1179
Reputation: 169160
Getting a reference to the ContextMenu
should be easy provided that you handle the ContextMenuOpening
event for the Grid
in the ControlTemplate
:
<ControlTemplate TargetType="{x:Type s:VacUnit}">
<Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}"
ContextMenu="{StaticResource VacUnitContextMenu}"
ContextMenuOpening="Grid_ContextMenuOpening">
</Grid>
</ControlTemplate>
What's a bit trickier is to get a reference to the TextBox
. You need to wait until it has been loaded:
private void Grid_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
Grid grid = (Grid)sender;
ContextMenu cm = grid.ContextMenu;
if (cm != null)
cm.Opened += Cm_Opened;
}
private void Cm_Opened(object sender, RoutedEventArgs e)
{
ContextMenu cm = (ContextMenu)sender;
cm.Opened -= Cm_Opened;
MenuItem header = cm.Items[0] as MenuItem;
MenuItem child = header.Items[0] as MenuItem;
StackPanel sp = child.Header as StackPanel;
(sp.Children[1] as TextBox).Background = Brushes.Yellow;
}
Upvotes: 2
Reputation: 20615
Probably e.Source
is not a Grid
where the context menu is defined.
You can search parent elements until you will find the element where the context menu is.
private void Xxx_ContextMenuOpening(object sender, ContextMenuEventArgs e)
{
var fe = e.Source as FrameworkElement;
var contextMenu = FindContextMenu(fe);
if(contextMenu != null)
{
// your code
}
}
// helper
private ContextMenu FindContextMenu(FrameworkElement fe)
{
if(fe == null)
{
return null;
}
if(fe.ContextMenu != null)
{
return fe.ContextMenu;
}
else
{
var parent = VisualTreeHelper.GetParent(fe) as FrameworkElement;
return FindContextMenu(parent);
}
}
Upvotes: 1