Specify .XAML part of UserControl in code-behind - c#

I wrote custom TreeView control.
XAML:
<TreeView x:Class="EArchiveMaster.View.MyTreeView"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300">
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<EventSetter Event="LostFocus" Handler="EventSetter_OnHandler" />
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
.cs
public partial class MyTreeView
{
public event Action SomeItemLostFocus;
public MyTreeView()
{
InitializeComponent();
}
private void EventSetter_OnHandler(object sender, RoutedEventArgs e)
{
e.Handled = true;
if (SomeItemLostFocus != null)
SomeItemLostFocus();
}
}
But when I try to use it I got well known error:
Cannot set Name attribute value 'TextBox' on element 'TextBox'. 'TextBox' is under the scope of element 'MyTreeView', which already had a name registered when it was defined in another scope.
I found some receipts how to fix this error. Namely, specify .xaml part of control in its code-behind.
But I have no idea how can I do this.

The code clearly shows you want to extend TreeView. Basically if you want to build control that can hold some content(which can be named...), like ContentControl, ItemsControl, etc.. it is always better to go with CustomControl. UserControl with XAML and CS code is not suitable for this case.
In your case, create a class like below and extend the functionalities,
public class MyTreeView : TreeView
{
public event Action SomeItemLostFocus;
public MyTreeView()
{
DefaultStyleKey = typeof(MyTreeView);
}
public override void OnLostFocus(object sender, RoutedEventArgs e)
{
e.Handled = true;
if (SomeItemLostFocus != null)
SomeItemLostFocus();
}
}
If you want to customize the look and feel, you should override the default Style of the control. This style should be available in generic.xaml file inside Themes folder. More information on Custom Control development is here.
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="IsExpanded"
Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected"
Value="{Binding IsSelected, Mode=TwoWay}" />
</Style>

I found solution appropriate for me. This it the way how to define Style of TreeViewItem in code, not in XAML. Now I have TreeView definded only in code-behind, therefore, error will not be risen.
public class MyTreeView : TreeView
{
public event RoutedEventHandler ItemLostLogicFocus;
protected override void OnInitialized(EventArgs e)
{
base.OnInitialized(e);
var itemContainerStyle = new Style
{
TargetType = typeof(TreeViewItem),
};
#region Binding
var expandedBinding = new Binding("IsExpanded")
{
Mode = BindingMode.TwoWay,
};
var selectedBinding = new Binding("IsSelected")
{
Mode = BindingMode.TwoWay,
};
#endregion
#region Setters
itemContainerStyle.Setters.Add(new Setter
{
Property = TreeViewItem.IsExpandedProperty,
Value = expandedBinding
});
itemContainerStyle.Setters.Add(new Setter
{
Property = TreeViewItem.IsSelectedProperty,
Value = selectedBinding
});
#endregion
#region EventSetters
itemContainerStyle.Setters.Add(new EventSetter
{
Event = LostFocusEvent,
Handler = new RoutedEventHandler(ItemLostLogicFocusHandler)
});
#endregion
ItemContainerStyle = itemContainerStyle;
}
private void ItemLostLogicFocusHandler(Object sender, RoutedEventArgs e)
{
e.Handled = true;
if (ItemLostLogicFocus != null)
ItemLostLogicFocus(sender, e);
}
}

Related

Access an element from UWP control instance that has a ControlTemplate assigned to it

I have the following code inside MainPage.xaml:
<Page ...>
<VariableSizedWrapGrid Name="ContentGrid"/>
</Page>
Just a primitive markup to create a grid control that will contain some CalendarView instances.\
Then in MainPage.xaml.cs I generate a couple of calendars:
namespace App1 {
public sealed partial class MainPage : Page {
public MainPage() {
this.InitializeComponent();
for (int i = 1; i <= 12; i++)
{
CalendarView instance = new CalendarView();
instance.CalendarViewDayItemChanging += myEvent;
ContentGrid.Children.Add(instance);
}
}
private void myEvent(CalendarView sender, CalendarViewDayItemChangingEventArgs args){...}
}
}
These calendars however, have internal content that has overriden style which is defined in App.xaml
<Application ...>
<Application.Resources>
<ResourceDictionary>
<Style x:Key="CalendarViewDayItemRevealStyle" TargetType="CalendarViewDayItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="CalendarViewDayItem">
<Grid x:Name="itemgrid" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="CalendarViewDayItem" BasedOn="{StaticResource CalendarViewDayItemRevealStyle}" />
</ResourceDictionary>
</Application.Resources>
</Application>
Every calendar control instance contains multiple CalendarViewDayItem controls.
Each of these CalendarViewDayItem controls will be rendering its content with the template above.
The question is: How to access instance specific grid element (here with name itemgrid)?
In an ideal world I would imagine something like this:
private void myEvent(CalendarView sender, CalendarViewDayItemChangingEventArgs args){
CalendarViewDayItem instance = args.Item;
ControlTemplate instance_template = instance.Template;
Grid g = (Grid)instance_template.getValue().getElementByName("itemgrid");
}
I also know that this access should work only when the instance is sufficiently constructed.
Also, maybe some per-instance binding witchcraft could work.
This is a similar question to How do I access an element of a control template from within code-behind
but we are in UWP here.
Try this:
private void Instance_CalendarViewDayItemChanging(CalendarView sender, CalendarViewDayItemChangingEventArgs args)
{
CalendarViewDayItem item = args.Item;
Grid grid = FindMyChildByName(item, "itemgrid") as Grid;
}
public static DependencyObject FindMyChildByName(DependencyObject parant, string ControlName)
{
int count = VisualTreeHelper.GetChildrenCount(parant);
for (int i = 0; i < count; i++)
{
var MyChild = VisualTreeHelper.GetChild(parant, i);
if (MyChild is FrameworkElement && ((FrameworkElement)MyChild).Name == ControlName)
return MyChild;
var FindResult = FindMyChildByName(MyChild, ControlName);
if (FindResult != null)
return FindResult;
}
return null;
}

Flyout RegionAdapter doesn't use slide effect for the first time

In my application I'm using Prism and MahApps.metro. I created a RegionAdapter for FlyoutsControl, this is working like a charm.
The only problem is, that when I first navigate the View into Flyout Region, the Flyout pops up instead of sliding in from the side.
I can imagine this is because it is created at runtime and added to the FlyoutsControl at runtime, but is there a possibility to create the Flyout, add it to the FlyoutsControl and then show it via Slide-In effect?
Just setting the IsOpen property to false and then to open doesn't work :(
I was trying to do the same thing and was having issues but later i figured out the solution.
First, define the region name FlyoutRegion on FlyoutsControl.
<mahApps:MetroWindow ...>
<mahApps:MetroWindow.Flyouts>
<mahApps:FlyoutsControl prism:RegionManager.RegionName="FlyoutRegion">
<mahApps:FlyoutsControl.ItemContainerStyle>
<Style TargetType="{x:Type mahApps:Flyout}">
<Setter Property="Header" Value="{Binding Header}" />
<Setter Property="IsOpen" Value="{Binding IsOpen}" />
<Setter Property="Position" Value="{Binding Position}" />
</Style>
</mahApps:FlyoutsControl.ItemContainerStyle>
</mahApps:FlyoutsControl>
</mahApps:MetroWindow.Flyouts>
</mahApps:MetroWindow>
Create the RegionAdapter and register it in the Bootstrapper.
[Export]
public class FlyoutsControlRegionAdapter : RegionAdapterBase<FlyoutsControl>
{
[ImportingConstructor]
public FlyoutsControlRegionAdapter(IRegionBehaviorFactory factory)
: base(factory)
{
}
protected override void Adapt(IRegion region, FlyoutsControl regionTarget)
{
region.ActiveViews.CollectionChanged += (s, e) =>
{
if (e.Action == NotifyCollectionChangedAction.Add)
{
foreach (FrameworkElement element in e.NewItems)
{
Flyout flyout = new Flyout();
flyout.Content = element;
flyout.DataContext = element.DataContext;
regionTarget.Items.Add(flyout);
}
}
};
}
protected override IRegion CreateRegion()
{
return new AllActiveRegion();
}
}
Inside Bootstrapper
protected override RegionAdapterMappings ConfigureRegionAdapterMappings()
{
var mappings = base.ConfigureRegionAdapterMappings();
mappings.RegisterMapping(typeof(FlyoutsControl), Container.GetExportedValue<FlyoutsControlRegionAdapter>());
return mappings;
}
Finally, register the desired View with FlyoutRegion.
regionManager.RegisterViewWithRegion("FlyoutRegion", typeof(FlyoutView));
The trick here is to expose the Header, IsOpen and Position properties in the ViewModel and associate it with FlyoutView.
You can refer the detail on this Code Project Link

change setter value in style

I'm programming in WPF(c#). I'm trying to change value in a setter of style.
my style is:
<Style TargetType="Control" x:Key="st">
<Setter Property="FontFamily" Value="Tahoma"/>
<Setter Property="FontSize" Value="14"/>
</Style>
and I use it in a button:
<Button x:Name="btnCancel" Style="{StaticResource st}" Content="انصراف" Canvas.Left="30" Canvas.Top="18" Width="139" Height="53" FontFamily="2 badr" FlowDirection="LeftToRight" Click="btnCancel_Click_1" />
and what I try to do is this code:
Style style = new Style();
style = (Style) Resources["st"];
Setter setter =(Setter) style.Setters[1];
setter.Value = 30;
after setting font size to 30 I get this error?
After a “SetterCollectionBase” is in use (sealed), it cannot be modified
How can I solve this problem?
The styles can be set only once (sealed after compiling), you can't change it with code
so the solutions are
create a style by code
Style st = new Style(typeof(System.Windows.Controls.Control));
st.Setters.Add(new Setter(Control.FontFamilyProperty, new FontFamily("Tahoma")));
st.Setters.Add(new Setter(Control.FontSizeProperty, 14.0));
later you can change it
st.Setters.OfType<Setter>().FirstOrDefault(X => X.Property == Control.FontSizeProperty).Value = 30.0;//safer than Setters[1]
or
change the property directly
btnCancel.FontSize=30.0;
Since you are doing pure UI and behind the code while some answers recommend you to use MVVM which will really make a lot of things easier.
Why do you need to manipulate the Style? Is it just for the button and you want to manipulate its FontSize? I assume you are doing this on the Click event of the button where it changes the fontsize.
Try this then
private void btnCancel_Click_1(object sender, RoutedEventArgs e)
{
var button = sender as Button;
if (button != null) button.FontSize = 30;
}
You'll need to create a view model, something like this (I'm using the MVVM Lite class ViewModelBase, you just need something that supports property change notification):
public class MyViewModel : ViewModelBase
{
private double _FontSize = 0.0;
public double FontSize
{
get { return this._FontSize; }
set { this._FontSize = value; RaisePropertyChanged(() => this.FontSize); }
}
}
Then create an instance of it in your window along with a getter:
public partial class Window1 : Window
{
public MyViewModel MyViewModel {get; set;}
public Window1()
{
InitializeComponent();
this.MyViewModel = new MyViewModel { FontSize = 80 };
}
}
And then finally you need to bind your style to use the value in the view model:
<Window.Resources>
<Style TargetType="Control" x:Key="st">
<Setter Property="FontFamily" Value="Tahoma"/>
<Setter Property="FontSize" Value="{Binding RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=Window}, Path=MyViewModel.FontSize}"/>
</Style>
</Window.Resources>

Saving a WPF canvas as an image following MVVM Pattern

I have a canvas, e.g. similar to this solution or many others using the ItemsControl.
Now I want a button which should be bound to an ICommand. This command should call a method of ViewModel class which can save the image.
The saving method is clear, but how do I do the binding following the MVVM pattern?
You could pass the Canvas to the ViewModel's Save method using a CommandParameter
<Button Content="Save"
Command="{Binding SaveCanvasCommand}"
CommandParameter="{Binding ElenementName=myCanvas}" ?>
<Canvas x:Name="myCanvas">
<!-- Stuff to save -->
</Canvas>
And somewhere in you ViewModel or Command you'd have
void SaveCanvasCommandExecute(object parameter)
{
UIElement toSave = (UIElement)parameter;
//.. You'd probably use RenderTargetBitmap here to save toSave.
}
If you don't want to reference UI elements in your ViewModel you could use an attached behaviour:
internal static class Behaviours
{
public static readonly DependencyProperty SaveCanvasProperty =
DependencyProperty.RegisterAttached("SaveCanvas", typeof(bool), typeof(Behaviours),
new UIPropertyMetadata(false, OnSaveCanvas));
public static void SetSaveCanvas(DependencyObject obj, bool value)
{
obj.SetValue(SaveCanvasProperty, value);
}
public static bool GetSaveCanvas(DependencyObject obj)
{
return (bool)obj.GetValue(SaveCanvasProperty);
}
private static void OnSaveCanvas(DependencyObject obj, DependencyPropertyChangedEventArgs e)
{
if ((bool)e.NewValue)
{
// Save code.....
}
}
}
Then in your ViewModel you have your Command that sets a property, also on your ViewModel:
public ICommand SaveCanvasCommand
{
get
{
if (_saveCanvasCommand == null)
_saveCanvasCommand = new RelayCommand(() => { IsSaveCanvas = true; });
return _saveCanvasCommand;
}
}
And the property which is bound to your View:
public bool IsSaveCanvas
{
get { return _isSaveCanvas; }
set
{
_isSaveCanvas = value;
RaisePropertyChanged("IsSaveCanvas");
}
}
Then hooking it all up in the Xaml looks like this:
Add a Trigger on the Control that binds the value of your ViewModel property to your attached behaviour:
<UserControl.Style>
<Style>
<Style.Triggers>
<DataTrigger Binding="{Binding IsSaveCanvas}" Value="True">
<Setter Property="wpfApplication1:Behaviours.SaveCanvas" Value="True"/>
</DataTrigger>
<DataTrigger Binding="{Binding IsSaveCanvas}" Value="False">
<Setter Property="wpfApplication1:Behaviours.SaveCanvas" Value="False"/>
</DataTrigger>
</Style.Triggers>
</Style>
</UserControl.Style>
And then bind your Button / MenuItem to the ViewModels Save Command:
<Canvas.ContextMenu>
<MenuItem Header="Save" Command="{Binding SaveCanvasCommand}"/>
</Canvas.ContextMenu>

Command Binding not working on a context sensitive menu?

I have an user control (ex: UserCtrlClass)with a tree view inside it
I have View model (ex: OBJViewModel) class for represent the actual items/data display on the tree view
Next I have a Tree View Model (ex: TreeViewModel), which has a list of OBJViewModel objects
Now in the code behind file of the user control, I have instantiated the tree view model class and set as the data context of the user control class
I need a context sensitive menu, which i need to display only when I right click on a specific item in the tree, so I have handled the right click event of the user control class and did the work there
But the commands are not working, The commands are derived from I command and instantiated in TreeViewModel class. i tried to debug my Command.execute was never hit! Any help would be appreciated as I am being a newbie to .net and wpf
TreeViewModel class
<UserControl Name="PFDBUserCtrl" x:Class="BFSimMaster.BFSMTreeview"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:BFSimMaster.ViewModel"
xmlns:cmd="clr-namespace:BFSimMaster.Commands"
mc:Ignorable="d"
d:DesignHeight="66" d:DesignWidth="300">
<UserControl.Resources>
<!--cmd:ActivateProjectCmd x:Key="CMDActivateProject"/-->
<!--cmd:DeActivateProjectCmd x:Key="CMDDeActivateProject"/-->
</UserControl.Resources>
<DockPanel>
<!-- PF Object Browser TREE -->
<TreeView Name="PFDataBrowser" ItemsSource="{Binding LevelOnePFObjects}" >
<TreeView.Resources>
<ContextMenu x:Key ="ProjectMenu" StaysOpen="true" >
<!-- Text="{Binding Source={StaticResource myDataSource}, Path=PersonName}-->
<!--MenuItem Header="Activate" Command="{Binding Source={StaticResource CMDActivateProject}}" CommandParameter="{Binding Path=PlacementTarget,RelativeSource={RelativeSource AncestorType=ContextMenu}}"/-->
<MenuItem Header="Activate" Command="{Binding DataContext.CMDActivateProject, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" CommandParameter="{Binding Path=PlacementTarget,RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
<MenuItem Header="Deactivate" Command="{Binding Source=TVViewModel, Path=CMDDeActivateProject}" CommandParameter="{Binding Path=PlacementTarget,RelativeSource={RelativeSource AncestorType=ContextMenu}}"/>
</ContextMenu>
</TreeView.Resources>
<TreeView.ItemContainerStyle>
<!-- This Style binds a TreeViewItem to a PFObject View Model.-->
<Style TargetType="{x:Type TreeViewItem}">
<EventSetter Event="MouseRightButtonDown" Handler="OnRightButtonDown"/>
<Setter Property="IsExpanded" Value="{Binding IsExpanded, Mode=TwoWay}" />
<Setter Property="IsSelected" Value="{Binding IsSelected, Mode=TwoWay}" />
<Setter Property="FontWeight" Value="Normal" />
<Style.Triggers>
<Trigger Property="IsSelected" Value="True">
<Setter Property="FontWeight" Value="Bold" />
</Trigger>
</Style.Triggers>
</Style>
</TreeView.ItemContainerStyle>
<TreeView.ItemTemplate>
<HierarchicalDataTemplate ItemsSource="{Binding Children}">
<TextBlock Text="{Binding Name}" />
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
</TreeView>
</DockPanel>
Code behind class
using System;
namespace BFSimMaster
{
public partial class BFSMTreeview : UserControl
{
readonly TreeViewItemViewModel mViewModelPFObjBrowserTree;
public BFSMTreeview()
{
InitializeComponent();
WApplication appPF = PFAPIUtils.APIInstance.GetApplication();
WDataObject User = appPF.GetCurrentUser();
// Get raw objects - tree data from a PF database.
//BFPFDataObject userdb = new BFPFDataObject(User,false,"*.IntPrj");
BFPFDataObject userdb = new BFPFDataObject(User, true);
// Create UI-friendly wrappers around the
// raw data objects (i.e. the view-model).
mViewModelPFObjBrowserTree = new TreeViewItemViewModel(userdb);
// Let the UI bind to the view-model.
base.DataContext = mViewModelPFObjBrowserTree;
}
public TreeViewItemViewModel TVViewModel
{
get { return mViewModelPFObjBrowserTree; }
}
private void OnRightButtonDown(object sender, MouseButtonEventArgs e)
{
//MessageBox.Show("Right Clicked on tree view");
if (sender is TreeViewItem)
{
e.Handled = true;
(sender as TreeViewItem).IsSelected = true;
string strObjectType = ((sender as TreeViewItem).Header as PFObjectViewModel).PFDataObject.mThisPFObject.GetClassName().GetString();
switch (strObjectType)
{
case "IntPrj":
(sender as TreeViewItem).ContextMenu = PFDataBrowser.Resources["ProjectMenu"] as System.Windows.Controls.ContextMenu;
(sender as TreeViewItem).ContextMenu.PlacementTarget = (sender as TreeViewItem);
break;
case "Folder":
(sender as TreeViewItem).ContextMenu = PFDataBrowser.Resources["ProjectMenu"] as System.Windows.Controls.ContextMenu;
break;
}
}
}
}
}
the TreeViewModel Class
using System;
namespace BFSimMaster.ViewModel
{
public class TreeViewItemViewModel
{
#region Data
readonly ReadOnlyCollection<PFObjectViewModel> mLevelOnePFObjects;
readonly PFObjectViewModel mRootOfPFObjects;
#endregion // Data
#region Constructor
public TreeViewItemViewModel(BFPFDataObject rootOfPFObjectsA)
{
this.CMDActivateProject = new ActivateProjectCmd();
this.CMDDeActivateProject = new DeActivateProjectCmd();
mRootOfPFObjects = new PFObjectViewModel(rootOfPFObjectsA);
mLevelOnePFObjects = new ReadOnlyCollection<PFObjectViewModel>(
new PFObjectViewModel[]
{
mRootOfPFObjects
});
}
#endregion // Constructor
public ICommand CMDActivateProject { get; set; }
public ICommand CMDDeActivateProject { get; set; }
public ReadOnlyCollection<PFObjectViewModel> LevelOnePFObjects
{
get { return mLevelOnePFObjects; }
}
}
}
A ContextMenu isn't part of the logical tree, so this binding "{Binding DataContext.CMDActivateProject, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}" wont work, because it simply has no ancestor of type UserControl. If you dont set the DataContext of the PlacementTarget manuelly, you could try
"{Binding PlacementTarget.DataContext.CMDActivateProject, RelativeSource={RelativeSource AncestorType={x:Type ContextMenu}}}"
I not 100% sure about the following, but I think this will just work, if youre using the ContextMenu property:
<Treeview>
<Treeview.ContextMenu>
<ContextMenu>
...
<ContextMenu>
<Treeview.ContextMenu>
...
The adventage here is, that you dont have to handle the rightbuttondown event in code-behind, it automatically opens if you right click on your treeview.
I've solved this problem by introducing VM class for MenuItem and setting context menu with ExtendedContextMenu.Items={Binding ContextMenu} attached property. MenuResourcesDictionary is ResourceDictionary.xaml with back-side .cs file (shown below).
To use it for your code you need to add IEnumerable<MenuItemVM> ContextMenu property on your tree model and put commands there (e.g. pass them to MenuItemVM constructor). And in the item style add <Setter Property="ExtendedContextMenu.Items" Value="{Binding DataContext.ContextMenu}" />
public static class ExtendedContextMenu
{
private static readonly StyleSelector _styleSelector = new ContextMenuItemStyleSelector();
public static readonly DependencyProperty ItemsProperty =
DependencyProperty.RegisterAttached("Items",
typeof(IEnumerable<MenuItemVM>),
typeof(ExtendedContextMenu),
new FrameworkPropertyMetadata(default(IEnumerable<MenuItemVM>), ItemsChanged));
public static void SetItems(DependencyObject element, IEnumerable<MenuItemVM> value)
{
element.SetValue(ItemsProperty, value);
}
public static IEnumerable<MenuItemVM> GetItems(DependencyObject element)
{
return (IEnumerable<MenuItemVM>)element.GetValue(ItemsProperty);
}
private static void ItemsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var target = (FrameworkElement)d;
var items = (IEnumerable<MenuItemVM>)e.NewValue;
var contextMenu = new ContextMenu();
contextMenu.ItemContainerStyleSelector = _styleSelector;
contextMenu.ItemsSource = items;
return contextMenu;
}
private static void AdjustContextMenuVisibility(ContextMenu menu)
{
menu.Visibility = menu.HasItems ? Visibility.Visible : Visibility.Hidden;
}
}
public class ContextMenuItemStyleSelector : StyleSelector
{
private static readonly MenuResourcesDictionary _resources = new MenuResourcesDictionary();
private static readonly Style _menuItemStyle = (Style)_resources[MenuResourcesDictionary.MenuItemStyleResourceKey];
private static readonly Style _separatorStyle = (Style)_resources[MenuResourcesDictionary.SeparatorStyleResourceKey];
public override Style SelectStyle(object item, DependencyObject container)
{
if (item == MenuItemVM.Separator)
return _separatorStyle;
return _menuItemStyle;
}
}
public sealed partial class MenuResourcesDictionary
{
public const string MenuItemStyleResourceKey = "MenuItemStyleResourceKey";
public const string DynamicMenuItemStyleResourceKey = "DynamicMenuItemStyleResourceKey";
public const string SeparatorStyleResourceKey = "SeparatorStyleResourceKey";
public const string LoadingStyleResourceKey = "LoadingMenuItemStyleResourceKey";
public MenuResourcesDictionary()
{
InitializeComponent();
}
}
Here is XAML styles:
<Style x:Key="{x:Static local:MenuResourcesDictionary.MenuItemStyleResourceKey}">
<Setter Property="MenuItem.Header" Value="{Binding Path=(menuVMs:MenuItemVM.Text)}" />
<Setter Property="MenuItem.Command" Value="{Binding Path=(menuVMs:MenuItemVM.Command)}" />
</Style>
<Style x:Key="{x:Static local:MenuResourcesDictionary.SeparatorStyleResourceKey}" TargetType="{x:Type MenuItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate>
<Separator />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
MenuItemVM class is more-or-less straighforward, so I don't write it here.
I Found the Answer for TreeView Context menu with and with out DataTemplate here:
TreeView ContextMenu MVVM Binding
MVVM binding command to contextmenu item

Categories