I love WPF

"jamais sans son interface"

I love WPF

"jamais sans son interface"

Control for menu Item collection

A simple CustomControl for using collection in MenuItem with another MenuItem

from article : https://www.codeproject.com/Articles/22834/MenuItems-Collections-within-a-MenuItem

opriginal source code : MenuItems_Src

CustomControl

 public class MenuItemCollection : MenuItem
    {
        static MenuItemCollection()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MenuItemCollection), new FrameworkPropertyMetadata(typeof(MenuItemCollection)));
        }

        #region Constructor & OnApplyTemplate

        public MenuItemCollection() { }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
        }
        #endregion

        #region Dependency Property     

        //public static readonly DependencyProperty IsCheckedBindingPathProperty = DependencyProperty.Register(
        //    "IsCheckedBindingPath", typeof(String), typeof(MenuItemCollection), new PropertyMetadata(""));

        //public String IsCheckedBindingPath
        //{
        //    get { return (String)GetValue(IsCheckedBindingPathProperty); }
        //    set { SetValue(IsCheckedBindingPathProperty, value); }
        //}

        #region TopSeparatorVisibility (DP SHORT)
        public Visibility TopSeparatorVisibility { get { return (Visibility)GetValue(TopSeparatorVisibilityProperty); } set { SetValue(TopSeparatorVisibilityProperty, value); } }
        public static readonly DependencyProperty TopSeparatorVisibilityProperty = DependencyProperty.Register("TopSeparatorVisibility", typeof(Visibility), typeof(MenuItemCollection), new PropertyMetadata(Visibility.Collapsed));
        #endregion

        #region BottomSeparatorVisibility (DP SHORT)
        public Visibility BottomSeparatorVisibility { get { return (Visibility)GetValue(BottomSeparatorVisibilityProperty); } set { SetValue(BottomSeparatorVisibilityProperty, value); } }
        public static readonly DependencyProperty BottomSeparatorVisibilityProperty = DependencyProperty.Register("BottomSeparatorVisibility", typeof(Visibility), typeof(MenuItemCollection), new PropertyMetadata(Visibility.Collapsed));
        #endregion       

        #region SelectCommand (DP SHORT)
        public ICommand SelectCommand { get { return (ICommand)GetValue(SelectCommandProperty); } set { SetValue(SelectCommandProperty, value); } }
        public static readonly DependencyProperty SelectCommandProperty = DependencyProperty.Register("SelectCommand", typeof(ICommand), typeof(MenuItemCollection), new PropertyMetadata(null));
        #endregion 

        #endregion
    }

    public class SepartorVisibilityConverter : IMultiValueConverter
    {
        public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
        {
            try
            {
                Visibility v = (Visibility)values[0];
                if (v == Visibility.Visible)
                {
                    v = (int)values[1] == 0 ? Visibility.Collapsed : v;
                }
                return v;
            }
            catch { }
            return Visibility.Collapsed;
        }

        public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }

and style in generic.xaml

 <!-- MENU ITEM COLLECTION -->
    <Style TargetType="{x:Type local:MenuItemCollection}">
        <Style.Resources>
            <local:SepartorVisibilityConverter x:Key="sepconv" />
        </Style.Resources>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="{x:Type local:MenuItemCollection}">
                    <Border Background="{TemplateBinding Background}"
                            BorderBrush="{TemplateBinding BorderBrush}"
                            BorderThickness="{TemplateBinding BorderThickness}">
                        <StackPanel>
                            <Separator>
                                <Separator.Visibility>
                                    <MultiBinding Converter="{StaticResource sepconv}">
                                        <Binding Path="TopSeparatorVisibility"
                                                 RelativeSource="{RelativeSource TemplatedParent}" />
                                        <Binding Path="ItemsSource.Count"
                                                 RelativeSource="{RelativeSource TemplatedParent}"  />
                                    </MultiBinding>
                                </Separator.Visibility>
                            </Separator>
                            <ItemsControl ItemsSource="{TemplateBinding ItemsSource}">
                                <ItemsControl.ItemTemplate>
                                    <DataTemplate>
                                        <MenuItem Header="{Binding .}"
                                                  HeaderTemplate="{Binding HeaderTemplate, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:MenuItemCollection}}}"
                                                  Command="{Binding SelectCommand, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:MenuItemCollection}}}"
                                                  CommandParameter="{Binding .}" />
                                    </DataTemplate>
                                </ItemsControl.ItemTemplate>
                            </ItemsControl>
                            <Separator >
                                <Separator.Visibility>
                                    <MultiBinding Converter="{StaticResource sepconv}">
                                        <Binding Path="BottomSeparatorVisibility"
                                                 RelativeSource="{RelativeSource TemplatedParent}" />
                                        <Binding Path="ItemsSource.Count"
                                                 RelativeSource="{RelativeSource TemplatedParent}" />
                                    </MultiBinding>
                                </Separator.Visibility>
                            </Separator>
                        </StackPanel>
                    </Border>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

for using

<local:MenuItemCollection ItemsSource="{Binding Items}"
                          SelectCommand="{Binding SelectCommand}"
                          TopSeparatorVisibility="Visible"
                          BottomSeparatorVisibility="Visible" />
<local:MenuItemCollection ItemsSource="{Binding Items2}"
                          SelectCommand="{Binding Select2Command}">
     <local:MenuItemCollection.HeaderTemplate>
          <DataTemplate>
              <TextBlock Text="{Binding Name}" />
          </DataTemplate>
     </local:MenuItemCollection.HeaderTemplate>
</local:MenuItemCollection>

with in MVVM

// for binding
 public ObservableCollection<string> Items { get; } = new ObservableCollection<string>();
 public ObservableCollection<object> Items2 { get; } = new ObservableCollection<object>();
.....
// create
 {
    Items.Add("alpha");
    Items.Add("beta");
    Items.Add("gamma");
    Items.Add("xxx");
    Items.Add("yyy");
}
{
    Items2.Add(new Item { Name = "alpha" });
    Items2.Add(new Item { Name = "beta" });
    Items2.Add(new Item { Name = "gamma" });
    Items2.Add(new Item { Name = "xxx" });
    Items2.Add(new Item { Name = "yyy" });
}
// Items class sample
public class Item
{
     public string Name { get; set; }
}
// and command for binding
#region Select (receive string)
RelayCommand _SelectCommand;
public ICommand SelectCommand
{
    get
    {
        if (_SelectCommand == null)
        {
            _SelectCommand = new RelayCommand(param => this.DoSelect(param),
                param => CanSelect(param));
        }
        return _SelectCommand;
    }
}
// can for Select
private bool CanSelect(object param)
{
    return !param.Equals("beta");
}

// function for Select
private void DoSelect(object param)
{
    Console.WriteLine("SELECT = " + param);
}
#endregion

#region Select2 (receive Item object)
RelayCommand _Select2Command;
public ICommand Select2Command
{
    get
    {
        if (_Select2Command == null)
        {
            _Select2Command = new RelayCommand(param => this.DoSelect2(param),
                    param => CanSelect2(param));
        }
        return _Select2Command;
    }
}
// can for Select2
private bool CanSelect2(object param)
{
    return (param as Item)?.Name.Equals("alpha") ?? false;
}

// function for Select2
private void DoSelect2(object param)
{
    Console.WriteLine("SELECT 2 = " + param);
}
#endregion

 

Laisser un commentaire

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *

Retour en haut