Cannot find sourcefor binding with reference 'ElementName=Field' - wpf

I have a context menu on a textbox that I'm trying to bind the isChecked property to one of the properties in that textbox's datacontext with a value converter.
The problem I'm having is very similar, I beleive, to this post... WPF MenuItem.Command binding to ElementName results to System.Windows.Data Error: 4 : Cannot find source for binding with reference
In there Aran Mulholland suggests 3 different solutions. The one I've been trying to get working, and have yet to see an actual working example of, is #2. I think this is the most MVVM friendly approach, and to that end the most elegant... then again, I'm pretty new to this.
Here is my xaml
<DataTemplate x:Key="SFTemplateWithContextMenu">
<TextBlock x:Name="Field" Text="{Binding Path=FieldName}" >
<TextBlock.ContextMenu>
<!--<ContextMenu PlacementTarget="{Binding ElementName=Field}" > -->
<ContextMenu DataContext="{Binding RelativeSource={RelativeSource Mode=Self}, Path=PlacementTarget.DataContext}">
<MenuItem Header="Rename..." />
<MenuItem Header="Field Type">
<MenuItem.Resources>
<Configurator:EnumToBooleanConverter x:Key="EnumToBooleanConverter" />
</MenuItem.Resources>
<!--<MenuItem Header="String" IsCheckable="True" IsChecked="{Binding Path=PlacementTarget.DataContext.FieldType, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static Configurator:TypeDesc.String}, PresentationTraceSources.TraceLevel=High}"/>-->
<MenuItem Header="String" IsCheckable="True" IsChecked="{Binding Path=FieldType, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource EnumToBooleanConverter}, ConverterParameter={x:Static Configurator:TypeDesc.String}, PresentationTraceSources.TraceLevel=High}"/>
</MenuItem>
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</DataTemplate>
I'm using the DataTemplate to populate the following ListBox...
<ListBox DnD:DragDropHelper.IsDragSource="True" Name="sourceFieldsLB" Height="238" HorizontalAlignment="Left" Margin="20,286,0,0" VerticalAlignment="Top" Width="150" ItemTemplate="{StaticResource SFTemplateWithContextMenu}" ItemsSource="{Binding Selection.SourceFields, Mode=TwoWay}" AllowDrop="True" >
I downloaded Snoop to look inside and see just what is going on. I've tried a couple of different methods with varying degrees of failure.
The commented out piece is the previous way I was trying to accomplish my goal. The problem there is that i was getting the error...
"cannot find source for binding with reference 'elementname=Field'" But the TextBlock shows using Snoop that its name IS Field.
In the current way I'm doing it I can see that the textblock has a local namescope and its name is Field - which is what I would expect and want. The ContextMenu value shows that it has a ContextMenu with 2 items... which is correct. So I click on ContextMenu to see how things look and low and behold the ContextMenu has no DataContext.
Any help and direction on this would be greatful. I'm not sure exactly what I'm missing here. I've looked around and whenever someone seems to get close to having this work they mention they found some "workaround" or other way to do it and never get it working. This HAS to have the ability to work... I'm just too new to this to see the missing piece.
I know it can be done to do a true MVVM way... right?

Bryce, the main problem is that ContextMenus are not part of the standard visual tree and the only real connection they have is via the PlacementTarget property. So, it's normally best to hook that up as soon as possible. So...
Given a ViewModel
public class ViewModel
{
public string Field { get; set; }
public string FieldType { get; set; }
}
And a MainWindow
<Window x:Class="ContextMenuSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBlock Text="{Binding Field}">
<TextBlock.ContextMenu>
<ContextMenu DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.DataContext}">
<MenuItem Header="{Binding FieldType}" />
</ContextMenu>
</TextBlock.ContextMenu>
</TextBlock>
</Grid>
</Window>
And an app.xaml.cs
using System;
using System.Collections.Generic;
using System.Configuration;
using System.Data;
using System.Linq;
using System.Windows;
namespace ContextMenuSample
{
/// <summary>
/// Interaction logic for App.xaml
/// </summary>
public partial class App : Application
{
protected override void OnStartup(StartupEventArgs e)
{
base.OnStartup(e);
var shell = new MainWindow();
shell.DataContext = new ViewModel { Field = "FirstName", FieldType = "String" };
shell.Show();
}
}
}
You can see that the DataContext for the ContextMenu gets hooked up correctly by the line
<ContextMenu DataContext="{Binding RelativeSource={RelativeSource Self}, Path=PlacementTarget.DataContext}">
and you should get a nicely behaved ContextMenu that talks to the underlying VieWModel.

Related

How can I bind to a parent UIElement within an ItemTemplate?

I'm trying to bind to a property of MainWindow, but from a ContextMenu within a DataTemplate. How can I achieve this?
I can't use ElementName, as the contextMenu isn't part of the visual tree
I can't use PlacementTarget, as this will give the UIElement produced by the DataTemplate
<Window x:Class="WpfApplication24.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ItemsControl ItemsSource="{Binding Data}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Border Padding="5" CornerRadius="10" BorderThickness="1" BorderBrush="Red">
<Border.ContextMenu>
<ContextMenu ItemsSource="{Binding <I want to bind to a property of MainWindow here>}"/>
</Border.ContextMenu>
<TextBlock Text="{Binding}"/>
</Border>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
You can have the window object in Tag of your Border and then can access it using PlacementTarget.Tag
<DataTemplate>
<Border Padding="5" CornerRadius="10" BorderThickness="1" BorderBrush="Red"
Tag="{Binding RelativeSource={RelativeSource FindAncestor,
AncestorType=Window}}">
<Border.ContextMenu>
<ContextMenu ItemsSource="{Binding PlacementTarget.Tag.PropertyName,
RelativeSource={RelativeSource Self}}"/>
</Border.ContextMenu>
<TextBlock Text="{Binding}"/>
</Border>
</DataTemplate>
What I used is a simple custom control wrapper e.g. MyContextMenu
...with just one line of code, something like...
public class MyContextMenu : ContextMenu
{
public override void EndInit()
{
base.EndInit();
NameScope.SetNameScope(this, NameScope.GetNameScope(App.Current.MainWindow));
}
}
...and use that instead of ContextMenu.
That always 'scopes' to the MainWindow which may not always be optimal - but you can use ElementName etc.
2) The other option is using NameScope.NameScope="{StaticResource myNameScope}"
NameScope.NameScope seems like an optimal solution - however, you cannot bind from it (and it binds 'too late').
But you can use {StaticResource ...} - and you make a class which wraps around MainWindow's scope.
Similar, but I found the above 'less disruptive' (you can pretty much write the code you'd normally write).
For more details take a look at this answers (and for more ideas)...
ElementName Binding from MenuItem in ContextMenu
How to access a control from a ContextMenu menuitem via the visual tree?

ItemsControl button click command

I need some quick help which is a road blocker for me now. I have Button in ItemsControl and I need to perform some task on Button click. I tried adding Command to Button in ItemsControl DataTemplate but its not working. Can anyone suggest how to proceed further.
<UserControl.Resources>
<DataTemplate x:key="mytask">
<TextBox Grid.Row="5" Grid.Column="2" Text="{Binding Path=PriorNote}" Grid.ColumnSpan="7" VerticalAlignment="Center" HorizontalAlignment="Left" Margin="0,5" Width="505" Foreground="Black"/>
<StatusBarItem Grid.Row="2" Grid.Column="8" Margin="8,7,7,8" Grid.RowSpan="2">
<Button x:Name="DetailsButton" Command="{Binding CommandDetailsButtonClick}">
</DataTemplate>
</UserControl.Resources>
<Grid>
<ItemsControl Grid.Row="1"
ItemsSource="{Binding ListStpRules}"
ItemTemplate="{StaticResource myTaskTemplate}" Background="Black"
AlternationCount="2" >
</ItemsControl>
</Grid>
and in ViewModel I have implemented code for Command. And its not working. Please suggest any solution for me to proceed further
The DataContext of each item in your ItemsControl is the item in the collection the ItemsControl is bound to. If this item contains the Command, your code should work fine.
However, this is not usually the case. Typically there is a ViewModel containing an ObservableCollection of items for the ItemsControl, and the Command to execute. If this is your case, you'll need to change the Source of your binding so it looks for the command in ItemsControl.DataContext, not ItemsControl.Item[X]
<Button Command="{Binding
RelativeSource={RelativeSource AncestorType={x:Type ItemsControl}},
Path=DataContext.MyCommand}" />
If your ViewModel has a property of type ICommand you can bind the Button's Command property to that:
XAML:
<DataTemplate DataType="{x:Type my:FooViewModel}">
<Button Content="Click!" Command="{Binding Path=DoBarCommand}" />
</DataTemplate>
C#:
public sealed class FooViewModel
{
public ICommand DoBarCommand
{
get;
private set;
}
//...
public FooViewModel()
{
this.DoBarCommand = new DelegateCommand(this.CanDoBar, this.DoBar);
}
}
Read this:
http://msdn.microsoft.com/en-us/magazine/dd419663.aspx
Implement a class similar to RelayCommand in the above article. Would make your further MVVM coding easier. :-)
Just a guess. Is CommandDetailsButtonClick defined in a ViewModel, which is DataContext of your UserControl (the one with ListStpRules property)?
DataContext of button in ItemTemplate is an item from ListStpRules, and if you command is not there then binding won't find it.
You can check diagnostic messages from wpf in Output window while debugging your application. It writes there if it can not resolve binding.

WPF + Binding Command and Header of a Context Menu Item using MVVM

I created a WPF application and am following MVVM Pattern. I have a context menu in my xaml and I need to bind the command and Header text. Using the following code I can bind the Header of the context menu with the "MenuItemName" which is a property in BOList which is an observable collection. My issue is that command is not getting fired? I changes the Item source of the Context Menu to datacontext
(DataContext="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}")
Command is working fine but my header is getting blank. Is there a way to bind my header and command of a menu item? Here the command MenuClick is a Icommand property in the VM and MenuItemName is a property inside BOList which is an observable collection binded to my ListBox.
<Grid>
<StackPanel Orientation="Vertical">
<Button x:Name="btnClickMe" Command="{Binding ButtonCommand}" Content="Click Me" />
<ListBox ItemsSource="{Binding BOList}" x:Name="lstDemo" SelectedItem="{Binding BussinessObj,Mode=OneWayToSource}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel x:Name="stkStyleRender" Orientation="Horizontal" Background="Cyan" Width="525" Tag="{Binding DataContext, RelativeSource={RelativeSource AncestorType={x:Type ListBox}}}" >
<TextBlock x:Name="txtId" Text="{Binding FirstName}"></TextBlock>
<TextBlock x:Name="txtName" Text="{Binding LastName}"></TextBlock>
<StackPanel.ContextMenu>
<ContextMenu x:Name="cntMnuTest" ItemsSource ="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource Self}}" >
<MenuItem Header="{Binding MenuItemName}" Command="{Binding MenuClick}" CommandParameter="Icon"></MenuItem>
</ContextMenu>
</StackPanel.ContextMenu>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
Hi Identified the issue.
If we set Item Source of the context menu to BOList (observable collection ) command wont get fired because the ICommand definition is in Window data context (vm).
We need to handle the code like wise.
Since debugging is not possible for binding , I was beating around the bush :-)
This link helped me a lot WPF Tutorial - Debug Databinding Issues in WPF
In context menu use DataContext instead of using Items source
then bind your menu item
try this:
<MenuItem Header="{Binding Path=PlacementTarget.MenuItemName, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}" Command="{Binding Path=PlacementTarget.MenuClick, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}" />

ContextMenu.PlacementTarget is not getting set, no idea why

<DataTemplate x:Key="_ItemTemplateA">
<Grid Tag="{Binding Path=DataContext.Command, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}}">
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<ContentControl Content="{Binding}" ContentTemplate="{StaticResource ContentTemplateB}" Grid.Row="0" />
<ContentControl Name="uiContentPresenter" Content="{Binding ContentView}" Grid.Row="1" Height="0" />
<ContentControl DataContext="{Binding IsContentDisplayed}" DataContextChanged="IsDisplayed_Changed" Visibility="Collapsed" />
<Grid.ContextMenu>
<ContextMenu>
<MenuItem Header="Text"
Command="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}"
CommandParameter="{Binding}" />
</ContextMenu>
</Grid.ContextMenu>
</Grid>
</DataTemplate>
The above data template is applied to an ItemsControl. The issue is that for the ContextMenu that is specified for the Grid, the PlacementTarget property is never actually getting set to anything so I cannot get to the Tag property of the Grid which is necessary for passing the Command that should execute on the parent UserControl down to the context menu. I've based this approach off of similar examples such as this: http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/0244fbb0-fd5f-4a03-bd7b-978d7cbe1be3/
I've not been able to identify any other good way to pass this command down. This is setup this way because we are using an MVVM approach so the command we have to execute lives in the View Model of the user control this template is applied in. I've tried explicitly setting the PlacementTarget in a few different ways but it still always shows up as not set.
I realise that this is old and answered, but it doesn't seem properly answered. I came across a similar post and left a full answer. You might like to take a look as you can get it working with just a few adjustments to your code.
First, name your view UserControl... I generally name all of mine This for simplicity. Then remembering that our view model is bound to the DataContext of the UserControl, we can bind to the view model using {Binding DataContext, ElementName=This}.
So now we can bind to the view model, we have to connect that with the ContextMenu.DataContext. I use the Tag property of the object with the ContextMenu (the PlacementTarget) as that connection, in this example, a Grid:
<DataTemplate x:Key="YourTemplate" DataType="{x:Type DataTypes:YourDataType}">
<Grid ContextMenu="{StaticResource Menu}" Tag="{Binding DataContext,
ElementName=This}">
...
</Grid>
</DataTemplate>
We can then access the view model properties and commands in the ContextMenu by binding the ContextMenu.DataContext property to the PlacementTarget.Tag property (of the Grid in our example):
<ContextMenu x:Key="Menu" DataContext="{Binding PlacementTarget.Tag, RelativeSource=
{RelativeSource Self}}">
<MenuItem Header="Delete" Command="{Binding DeleteFile}" CommandParameter=
"{Binding PlacementTarget.DataContext, RelativeSource={RelativeSource
AncestorType=ContextMenu}}" CommandTarget="{Binding PlacementTarget,
RelativeSource={RelativeSource Self}}" />
</ContextMenu>
Note the binding on the MenuItem.CommandTarget property. Setting this ensures that the target element on which the specified command is raised is the PlacementTarget, or the Grid in this case.
Also note the CommandParameter binding. This binds to the DataContext of the PlacementTarget, or the Grid in this case. The DataContext of the Grid will be inherited from the DataTemplate and so your data item is now bound to the object parameter in your Command if you're using some implementation of the ICommand interface:
public bool CanExecuteDeleteFileCommand(object parameter)
{
return ((YourDataType)parameter).IsInvalid;
}
public void ExecuteDeleteFileCommand(object parameter)
{
Delete((YourDataType)parameter);
}
Or if you are using some kind of RelayCommand delegates directly in your view model:
public ICommand Remove
{
get
{
return new ActionCommand(execute => Delete((YourDataType)execute),
canExecute => return ((YourDataType)canExecute).IsInvalid);
}
}
We have the same problem, but it works randomly. A contextmenu inside the controltemplate in a style for a listbox. We have tried to move the contextmenu to different levels inside the template but the same error occurs.
We think it might be connected to the refreshing of our ICollectionView that is the itemssource of the ListBox.
It seems that when the view refreshes the relative source binding inside the contextmenu is being evaluated before the PlacementTarget is being set.
It feels like a bug in either collectionviewsource or the ContextMenu of WPF...
Here is a working standalone XAML-only example based on your test case: a ContextMenu that retrieves a Command from the DataContext of its PlacementTarget using a Tag. You can reintroduce portions of your code until it stops working to try to find where the problem is:
<Grid>
<Grid.Resources>
<PointCollection x:Key="sampleData">
<Point X="10" Y="20"/>
<Point X="30" Y="40"/>
</PointCollection>
<DataTemplate x:Key="_ItemTemplateA">
<Grid Tag="{Binding Path=DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type DockPanel}}}">
<TextBlock Text="{Binding X}"/>
<Grid.ContextMenu>
<ContextMenu>
<MenuItem Header="{Binding Path=PlacementTarget.Tag, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ContextMenu}}}" CommandParameter="{Binding}"/>
</ContextMenu>
</Grid.ContextMenu>
</Grid>
</DataTemplate>
</Grid.Resources>
<DockPanel DataContext="{x:Static ApplicationCommands.Open}">
<ListBox ItemTemplate="{StaticResource _ItemTemplateA}" ItemsSource="{StaticResource sampleData}"/>
</DockPanel>
</Grid>
In this post,
ContextMenu.PlacementTarget is filled up from ContextMenuService.PlacementTarget when you do right click with mouse on button.
It means ContextMenu.PlacementTarget is filled up when the menu is shown up. You can check that by snoop.
EDIT 1
This code works fine.
<DataGrid.RowStyle>
<Style TargetType="DataGridRow" BasedOn="{StaticResource DataGridRowBaseStyle}">
<Setter Property="Tag" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGrid}, Path=DataContext}"/>
<Setter Property="ContextMenu">
<Setter.Value>
<ContextMenu Style="{StaticResource ContextMenuStyle}"
ItemContainerStyle="{StaticResource MenuItemStyle}">
<MenuItem Header="Enable" Command="{Binding Path=PlacementTarget.Tag.(viewModels:PrinterListPageViewModel.EnableCommand), RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>
</Setter.Value>
</Setter>
</Style>
</DataGrid.RowStyle>

ElementName Binding from MenuItem in ContextMenu

Has anybody else noticed that Bindings with ElementName do not resolve correctly for MenuItem objects that are contained within ContextMenu objects? Check out this sample:
<Window x:Class="EmptyWPF.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
x:Name="window">
<Grid x:Name="grid" Background="Wheat">
<Grid.ContextMenu>
<ContextMenu x:Name="menu">
<MenuItem x:Name="menuItem" Header="Window" Tag="{Binding ElementName=window}" Click="MenuItem_Click"/>
<MenuItem Header="Grid" Tag="{Binding ElementName=grid}" Click="MenuItem_Click"/>
<MenuItem Header="Menu" Tag="{Binding ElementName=menu}" Click="MenuItem_Click"/>
<MenuItem Header="Menu Item" Tag="{Binding ElementName=menuItem}" Click="MenuItem_Click"/>
</ContextMenu>
</Grid.ContextMenu>
<Button Content="Menu"
HorizontalAlignment="Center" VerticalAlignment="Center"
Click="MenuItem_Click" Tag="{Binding ElementName=menu}"/>
<Menu HorizontalAlignment="Center" VerticalAlignment="Bottom">
<MenuItem x:Name="anotherMenuItem" Header="Window" Tag="{Binding ElementName=window}" Click="MenuItem_Click"/>
<MenuItem Header="Grid" Tag="{Binding ElementName=grid}" Click="MenuItem_Click"/>
<MenuItem Header="Menu" Tag="{Binding ElementName=menu}" Click="MenuItem_Click"/>
<MenuItem Header="Menu Item" Tag="{Binding ElementName=anotherMenuItem}" Click="MenuItem_Click"/>
</Menu>
</Grid>
</Window>
All of the bindings work great except for the bindings contained within the ContextMenu. They print an error to the Output window during runtime.
Any one know of any work arounds? What's going on here?
I found a much simpler solution.
In the code behind for the UserControl:
NameScope.SetNameScope(contextMenu, NameScope.GetNameScope(this));
As said by others, the 'ContextMenu' is not contained in the visual tree and an 'ElementName' binding won't work. Setting the context menu's 'NameScope' as suggested by the accepted answer only works if the context menu is not defined in a 'DataTemplate'. I have solved this by using the {x:Reference} Markup-Extension which is similar to the 'ElementName' binding but resolves the binding differently, bypassing the visual tree. I consider this to be far more readable than using 'PlacementTarget'. Here is an example:
<Image Source="{Binding Image}">
<Image.ContextMenu>
<ContextMenu>
<MenuItem Header="Delete"
Command="{Binding Source={x:Reference Name=Root}, Path=DataContext.RemoveImage}"
CommandParameter="{Binding}" />
</ContextMenu>
</Image.ContextMenu>
</Image>
According to the MSDN-documentation
x:Reference is a construct defined in XAML 2009. In WPF, you can use
XAML 2009 features, but only for XAML that is not WPF markup-compiled.
Markup-compiled XAML and the BAML form of XAML do not currently
support the XAML 2009 language keywords and features.
whatever that means... Works for me, though.
Here's another xaml-only workaround. (This also assumes you want what's inside the DataContext, e.g., you're MVVMing it)
Option one, where the parent element of the ContextMenu is not in a DataTemplate:
Command="{Binding PlacementTarget.DataContext.MyCommand,
RelativeSource={RelativeSource AncestorType=ContextMenu}}"
This would work for OP's question. This won't work if you are inside of a DataTemplate. In these cases, the DataContext is often one of many in a collection, and the ICommand you wish to bind to is a sibling property of the collection within the same ViewModel (the DataContext of the Window, say).
In these cases, you can take advantage of the Tag to temporarily hold the parent DataContext which contains both the collection AND your ICommand:
class ViewModel
{
public ObservableCollection<Derp> Derps { get;set;}
public ICommand DeleteDerp {get; set;}
}
and in the xaml
<!-- ItemsSource binds to Derps in the DataContext -->
<StackPanel
Tag="{Binding DataContext, ElementName=root}">
<StackPanel.ContextMenu>
<ContextMenu>
<MenuItem
Header="Derp"
Command="{Binding PlacementTarget.Tag.DeleteDerp,
RelativeSource={RelativeSource
AncestorType=ContextMenu}}"
CommandParameter="{Binding PlacementTarget.DataContext,
RelativeSource={RelativeSource AncestorType=ContextMenu}}">
</MenuItem>
Context menus are tricky to bind against. They exist outside the visual tree of your control, hence they can't find your element name.
Try setting the datacontext of your context menu to its placement target. You have to use RelativeSource.
<ContextMenu
DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}"> ...
After experimenting a bit, I discovered one work around:
Make top level Window/UserControl implement INameScope and set NameScope of ContextMenu to the top level control.
public class Window1 : Window, INameScope
{
public Window1()
{
InitializeComponent();
NameScope.SetNameScope(contextMenu, this);
}
// Event handlers and etc...
// Implement INameScope similar to this:
#region INameScope Members
Dictionary<string, object> items = new Dictionary<string, object>();
object INameScope.FindName(string name)
{
return items[name];
}
void INameScope.RegisterName(string name, object scopedElement)
{
items.Add(name, scopedElement);
}
void INameScope.UnregisterName(string name)
{
items.Remove(name);
}
#endregion
}
This allows the context menu to find named items inside of the Window. Any other options?
I'm not sure why resort to magic tricks just to avoid a one line of code inside the eventhandler for the mouse click you already handle:
private void MenuItem_Click(object sender, System.Windows.RoutedEventArgs e)
{
// this would be your tag - whatever control can be put as string intot he tag
UIElement elm = Window.GetWindow(sender as MenuItem).FindName("whatever control") as UIElement;
}

Resources