Reputation: 3
i try to bind the TextBox's text in MenuItem's header to MenuItem's Tag property. but it won't work correct, always get Null in Tag property.
the code is like below...
<Button x:Name="Button1" Content="Test" HorizontalAlignment="Left" Width="182" Height="34" VerticalAlignment="Top" Margin="160,113,0,0">
<Button.ContextMenu>
<ContextMenu PlacementTarget="{Binding ElementName=Button1}" Placement="Bottom">
<MenuItem Tag="{Binding ElementName=TextBox1, Path=Text}" Click="MessageBox_ShowTag">
<MenuItem.Header>
<Grid Height="25" MinWidth="153">
<Label Content="Label1" Width="86" HorizontalAlignment="Left" VerticalContentAlignment="Center"/>
<TextBox x:Name="TextBox1" VerticalContentAlignment="Center" Margin="91,0,0,0"/>
</Grid>
</MenuItem.Header>
</MenuItem>
</ContextMenu>
</Button.ContextMenu>
</Button>
When click on menuitem, call the MessageBox to show the tag in MenuItem ( MessageBox.Show( ( sender as MenuItem ).Tag?.ToString() ); )
MessageBox has show but content is always empty.
how can i bind to textbox?
Upvotes: 0
Views: 269
Reputation: 81233
Like mentioned in the comment also, there could be better solution to actual problem you are trying to solve.
But anyhow if you want solution for your specific problem it can be solved by using x:Reference
in place of ElementName
like this:
<MenuItem Tag="{Binding Source={x:Reference TextBox1}, Path=Text}"/>
ElementName is not working because VisualTree is different. In case interested read further here - ElementName v/s x:Reference.
Upvotes: 1
Reputation: 5373
I don't know why you have to bind it like that. An alternative would be to bind to a property (here: MyText
) that implements INotifyPropertyChanged
, and then pass the DataContext
to the menu like this:
<Button x:Name="Button1" Content="Test" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Button.ContextMenu>
<ContextMenu Placement="Bottom" DataContext="{Binding Path=PlacementTarget.DataContext, RelativeSource={RelativeSource Self}}">
<MenuItem>
<MenuItem.Header>
<Grid Height="25" MinWidth="153">
<Label Content="Label1" Width="86" HorizontalAlignment="Left" VerticalContentAlignment="Center"/>
<TextBox Name="TextBox1" Text="{Binding Path=MyText}"
VerticalContentAlignment="Center" Margin="91,0,0,0"/>
</Grid>
</MenuItem.Header>
</MenuItem>
</ContextMenu>
</Button.ContextMenu>
</Button>
And then not relay on Click
event to get the TextBox
value at all.
If you want to know why your binding doesn't work, its because your MenuItem
can't find an object named TextBox1
in its Namescope
. If you must (namescopes are a bit tricky), you may make it work by creating a new Namescope for your MenuItem
and registering the name for the TextBox
:
NameScope.SetNameScope(mi1, new NameScope());
mi1.RegisterName("TextBox1", TextBox1);
where mi1
is the name of your MenuItem
, then your binding will work:
<Button x:Name="Button1" Content="Test" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
<Button.ContextMenu>
<ContextMenu Placement="Bottom">
<MenuItem Tag="{Binding ElementName=TextBox1, Path=Text}" Click="MessageBox_ShowTag" Name="mi1">
<MenuItem.Header>
<Grid Height="25" MinWidth="153">
<Label Content="Label1" Width="86" HorizontalAlignment="Left" VerticalContentAlignment="Center"/>
<TextBox Name="TextBox1" VerticalContentAlignment="Center" Margin="91,0,0,0"/>
</Grid>
</MenuItem.Header>
</MenuItem>
</ContextMenu>
</Button.ContextMenu>
</Button>
Also, avoid x:Name
whenever you can. It can cause some nasty memory leaks. Use Name instead.
Upvotes: 1
Reputation: 1
Try binding via RelativeSource
:
<TextBox x:Name="TextBox1" Text="{Binding Path=Tag, RelativeSource={RelativeSource AncestorType={x:Type MenuItem}}}" VerticalContentAlignment="Center" Margin="91,0,0,0"/>
Upvotes: 0