I am stumped yet again from WPF. Sometimes things just are not straight forward! I have searched high and low for an answer but everything I have tried has failed.
I am trying to create a generic Copy and Paste menu by using a datatemplate. Then each control I wish to use that contextmenu I can just set the template of that control and provide the correct function bindings and in theory it should just work. Instead of duplicating the same menu in each custom control file. But apparently ContextMenu's are just a nightmare.
What I know:
- Context menus do not inherit the data context because they are not part of the visual tree
- I can use DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}} to get around this and it should inherit.
- I cannot use WPF inspector to find out if the datacontext of the context menu is NULL. Which is annoying. Maybe there is another way. But there are no errors in the output so I have to assume its not null.
So based on my code it SHOULD WORK. Can somebody please point out the exceptionally magical combination of , "oh wait, in WPF you cant do this, and this and if this and this equals this". Answer? :)
Here is my custom control (Excuse the mess I have been hacking to try get this working!)
/// <summary>
/// Interaction logic for Pointer.xaml
/// </summary>
public partial class Expander : UserControl
{
/// <summary>
/// Command_ArrayAdd
/// </summary>
public class PasteCommand : ICommand
{
public PasteCommand(Expander _parent)
{
m_Parent = _parent;
}
/// <summary>
/// Execute
/// </summary>
public bool Execute()
{
return true;
}
/// <summary>
/// UnExecute
/// </summary>
public void UnExecute()
{
}
Expander m_Parent;
}
/// <summary>
/// Command_ArrayAdd
/// </summary>
public class CopyCommand : ICommand
{
public CopyCommand()
{
}
/// <summary>
/// Execute the change on the field
/// </summary>
public bool Execute()
{
return true;
}
/// <summary>
/// Undo the change on the field
/// </summary>
public void UnExecute()
{
}
}
/// <summary>
///
/// </summary>
public PasteCommand OnPasteCommand
{
get { return m_OnPasteCommand; }
set { m_OnPasteCommand = value; }
}
PasteCommand m_OnPasteCommand;
/// <summary>
///
/// </summary>
public CopyCommand OnCopyCommand
{
get { return m_OnCopyCommand; }
set { m_OnCopyCommand = value; }
}
CopyCommand m_OnCopyCommand;
public Expander(Database.DatabaseInstance.Struct _dbStruct, string _headerName)
{
try
{
InitializeComponent();
}
catch (System.Exception ex)
{
ErrorConsole.Instance.LogError(ex.Message + "\n" + ex.InnerException.Message);
}
m_dbStruct = _dbStruct;
DataContext = this;
m_HeaderName = _headerName;
ExpanderLabel.Content = m_HeaderName;
//AddHandler(CustomEvents.Copy, new RoutedEventHandler(OnCopyEvent));
m_OnCopyCommand = new CopyCommand();
m_OnPasteCommand = new PasteCommand(this);
}
private void OnUnloaded(object obj, RoutedEventArgs e)
{
//RemoveHandler(CustomEvents.Copy, new RoutedEventHandler(OnCopyEvent));
}
void OnMenuOpened(object obj, RoutedEventArgs e)
{
//string _clipboardData = (string)Clipboard.GetDataObject().GetData(DataFormats.Text);
//((MenuItem)ExpanderLabel.Template.FindName("PasteMenuItem", ExpanderLabel)).IsEnabled = View.ViewModel.CanCopyFromTo(_clipboardData, m_dbStruct);
}
void _OnCopyCommand()
{
Clipboard.SetDataObject(m_dbStruct.Serialized);
}
void _OnPasteCommand()
{
CommandManager.Instance.Queue(new Database.DatabaseCommands.Command_PasteStruct(m_dbStruct, null));
}
Database.DatabaseInstance.Struct m_dbStruct;
string m_HeaderName;
}
Here is my data template:
<Style x:Key="RightClickCopyPasteLabel" TargetType="{x:Type Label}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="Label">
<Label>
<Label.ContextMenu>
<ContextMenu DataContext="{Binding PlacementTarget, RelativeSource={RelativeSource Self}}">
<MenuItem x:Name="CopyMenuItem" Command="{Binding DataContext.OnCopyCommand, PresentationTraceSources.TraceLevel=High}" InputGestureText="Ctrl+C" Header="Copy" />
<MenuItem x:Name="PasteMenuItem" Command="{Binding DataContext.OnPasteCommand, PresentationTraceSources.TraceLevel=High}" InputGestureText="Ctrl+P" Header="Paste" />
</ContextMenu>
</Label.ContextMenu>
</Label>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="true">
<Setter Property="FontWeight" Value="Bold"/>
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
EDIT:
On another thread I found a way of outputting a bunch more data but unfortunately this doesn't mean anything to me. This is what I get when I right click:
System.Windows.Data Warning: 96 : BindingExpression (hash=13029119): Got PropertyChanged event from MenuItem (hash=24459401) for DataContext
System.Windows.Data Warning: 79 : BindingExpression (hash=13029119): Deactivate
System.Windows.Data Warning: 103 : BindingExpression (hash=13029119): Replace item at level 0 with {NullDataItem}
System.Windows.Data Warning: 103 : BindingExpression (hash=13029119): Replace item at level 1 with {NullDataItem}
System.Windows.Data Warning: 78 : BindingExpression (hash=13029119): Activate with root item Label (hash=25041938)
System.Windows.Data Warning: 107 : BindingExpression (hash=13029119): At level 0 using cached accessor for Label.DataContext: DependencyProperty(DataContext)
System.Windows.Data Warning: 104 : BindingExpression (hash=13029119): Replace item at level 0 with Label (hash=25041938), using accessor DependencyProperty(DataContext)
System.Windows.Data Warning: 101 : BindingExpression (hash=13029119): GetValue at level 0 from Label (hash=25041938) using DependencyProperty(DataContext): Expander (hash=20086501)
System.Windows.Data Warning: 107 : BindingExpression (hash=13029119): At level 1 using cached accessor for Expander.OnCopyCommand: RuntimePropertyInfo(OnCopyCommand)
System.Windows.Data Warning: 104 : BindingExpression (hash=13029119): Replace item at level 1 with Expander (hash=20086501), using accessor RuntimePropertyInfo(OnCopyCommand)
System.Windows.Data Warning: 101 : BindingExpression (hash=13029119): GetValue at level 1 from Expander (hash=20086501) using RuntimePropertyInfo(OnCopyCommand): CopyCommand (hash=9651034)
System.Windows.Data Warning: 80 : BindingExpression (hash=13029119): TransferValue - got raw value CopyCommand (hash=9651034)
System.Windows.Data Warning: 84 : BindingExpression (hash=13029119): TransferValue - implicit converter produced <null>
System.Windows.Data Warning: 89 : BindingExpression (hash=13029119): TransferValue - using final value <null>
System.Windows.Data Warning: 96 : BindingExpression (hash=58885068): Got PropertyChanged event from MenuItem (hash=65477567) for DataContext
System.Windows.Data Warning: 79 : BindingExpression (hash=58885068): Deactivate
System.Windows.Data Warning: 103 : BindingExpression (hash=58885068): Replace item at level 0 with {NullDataItem}
System.Windows.Data Warning: 103 : BindingExpression (hash=58885068): Replace item at level 1 with {NullDataItem}
System.Windows.Data Warning: 78 : BindingExpression (hash=58885068): Activate with root item Label (hash=25041938)
System.Windows.Data Warning: 107 : BindingExpression (hash=58885068): At level 0 using cached accessor for Label.DataContext: DependencyProperty(DataContext)
System.Windows.Data Warning: 104 : BindingExpression (hash=58885068): Replace item at level 0 with Label (hash=25041938), using accessor DependencyProperty(DataContext)
System.Windows.Data Warning: 101 : BindingExpression (hash=58885068): GetValue at level 0 from Label (hash=25041938) using DependencyProperty(DataContext): Expander (hash=20086501)
System.Windows.Data Warning: 107 : BindingExpression (hash=58885068): At level 1 using cached accessor for Expander.OnPasteCommand: RuntimePropertyInfo(OnPasteCommand)
System.Windows.Data Warning: 104 : BindingExpression (hash=58885068): Replace item at level 1 with Expander (hash=20086501), using accessor RuntimePropertyInfo(OnPasteCommand)
System.Windows.Data Warning: 101 : BindingExpression (hash=58885068): GetValue at level 1 from Expander (hash=20086501) using RuntimePropertyInfo(OnPasteCommand): PasteCommand (hash=50152377)
System.Windows.Data Warning: 80 : BindingExpression (hash=58885068): TransferValue - got raw value PasteCommand (hash=50152377)
System.Windows.Data Warning: 84 : BindingExpression (hash=58885068): TransferValue - implicit converter produced <null>
System.Windows.Data Warning: 89 : BindingExpression (hash=58885068): TransferValue - using final value <null>
System.Windows.Data Warning: 96 : BindingExpression (hash=13029119): Got PropertyChanged event from MenuItem (hash=24459401) for DataContext
System.Windows.Data Warning: 79 : BindingExpression (hash=13029119): Deactivate
System.Windows.Data Warning: 103 : BindingExpression (hash=13029119): Replace item at level 0 with {NullDataItem}
System.Windows.Data Warning: 103 : BindingExpression (hash=13029119): Replace item at level 1 with {NullDataItem}
System.Windows.Data Warning: 78 : BindingExpression (hash=13029119): Activate with root item <null>
System.Windows.Data Warning: 106 : BindingExpression (hash=13029119): Item at level 0 is null - no accessor
System.Windows.Data Warning: 103 : BindingExpression (hash=13029119): Replace item at level 1 with {NullDataItem}
System.Windows.Data Warning: 80 : BindingExpression (hash=13029119): TransferValue - got raw value {DependencyProperty.UnsetValue}
System.Windows.Data Warning: 88 : BindingExpression (hash=13029119): TransferValue - using fallback/default value <null>
System.Windows.Data Warning: 89 : BindingExpression (hash=13029119): TransferValue - using final value <null>
System.Windows.Data Warning: 96 : BindingExpression (hash=58885068): Got PropertyChanged event from MenuItem (hash=65477567) for DataContext
System.Windows.Data Warning: 79 : BindingExpression (hash=58885068): Deactivate
System.Windows.Data Warning: 103 : BindingExpression (hash=58885068): Replace item at level 0 with {NullDataItem}
System.Windows.Data Warning: 103 : BindingExpression (hash=58885068): Replace item at level 1 with {NullDataItem}
System.Windows.Data Warning: 78 : BindingExpression (hash=58885068): Activate with root item <null>
System.Windows.Data Warning: 106 : BindingExpression (hash=58885068): Item at level 0 is null - no accessor
System.Windows.Data Warning: 103 : BindingExpression (hash=58885068): Replace item at level 1 with {NullDataItem}
System.Windows.Data Warning: 80 : BindingExpression (hash=58885068): TransferValue - got raw value {DependencyProperty.UnsetValue}
System.Windows.Data Warning: 88 : BindingExpression (hash=58885068): TransferValue - using fallback/default value <null>
System.Windows.Data Warning: 89 : BindingExpression (hash=58885068): TransferValue - using final value <null>
ICommand
implementation does not haveExecute(object)
method, so wondering whatICommand
you are using here? it should beSystem.Windows.Input.ICommand
– pushpraj