using System.Collections.Generic; using System.Linq; using System.Windows; using System.Windows.Controls; namespace Developpez.Dotnet.Windows.Behaviors { /// /// Fournit des propriétés attachées pour ajouter des fonctionnalités aux menus /// public static class MenuBehavior { /// /// Obtient la valeur de la propriété attachée OptionGroupName /// /// L'objet pour lequel on veut obtenir la valeur /// Le nom du groupe d'options auquel appartient cet élément [AttachedPropertyBrowsableForType(typeof(MenuItem))] public static string GetOptionGroupName(MenuItem obj) { return (string)obj.GetValue(OptionGroupNameProperty); } /// /// Définit la valeur de la propriété attachée OptionGroupName /// /// L'objet pour lequel on veut définir la valeur /// Le nom du groupe d'options auquel appartient cet élément public static void SetOptionGroupName(MenuItem obj, string value) { obj.SetValue(OptionGroupNameProperty, value); } /// /// Identifiant de la propriété OptionGroupName /// public static readonly DependencyProperty OptionGroupNameProperty = DependencyProperty.RegisterAttached( "OptionGroupName", typeof(string), typeof(MenuBehavior), new UIPropertyMetadata( null, OptionGroupNameChanged)); private static void OptionGroupNameChanged(DependencyObject o, DependencyPropertyChangedEventArgs e) { var menuItem = o as MenuItem; if (menuItem == null) return; var oldValue = (string)e.OldValue; var newValue = (string)e.NewValue; if (!string.IsNullOrEmpty(oldValue)) { RemoveFromOptionGroup(menuItem); } if (!string.IsNullOrEmpty(newValue)) { AddToOptionGroup(menuItem); } } private static Dictionary> GetOptionGroups(DependencyObject obj) { return (Dictionary>)obj.GetValue(OptionGroupsPropertyKey.DependencyProperty); } private static void SetOptionGroups(DependencyObject obj, Dictionary> value) { obj.SetValue(OptionGroupsPropertyKey, value); } private static readonly DependencyPropertyKey OptionGroupsPropertyKey = DependencyProperty.RegisterAttachedReadOnly("OptionGroups", typeof(Dictionary>), typeof(MenuBehavior), new UIPropertyMetadata(null)); private static HashSet GetOptionGroup(MenuItem menuItem, bool create) { string groupName = GetOptionGroupName(menuItem); if (groupName == null) return null; if (menuItem.Parent == null) return null; var optionGroups = GetOptionGroups(menuItem.Parent); if (optionGroups == null) { if (create) { optionGroups = new Dictionary>(); SetOptionGroups(menuItem.Parent, optionGroups); } else { return null; } } HashSet group; if (!optionGroups.TryGetValue(groupName, out group) && create) { group = new HashSet(); optionGroups[groupName] = group; } return group; } private static void AddToOptionGroup(MenuItem menuItem) { var group = GetOptionGroup(menuItem, true); if (group == null) return; if (group.Add(menuItem)) { menuItem.Checked += menuItem_Checked; menuItem.Unchecked += menuItem_Unchecked; } } private static void RemoveFromOptionGroup(MenuItem menuItem) { var group = GetOptionGroup(menuItem, false); if (group == null) return; if (group.Remove(menuItem)) { menuItem.Checked -= menuItem_Checked; menuItem.Unchecked -= menuItem_Unchecked; } } private static void menuItem_Checked(object sender, RoutedEventArgs e) { MenuItem menuItem = sender as MenuItem; if (menuItem == null) return; string groupName = GetOptionGroupName(menuItem); if (groupName == null) return; // More than 1 checked option is allowed if (groupName.EndsWith("*") || groupName.EndsWith("+")) return; var group = GetOptionGroup(menuItem, false); if (group == null) return; foreach (var item in group) { if (item != menuItem) item.IsChecked = false; } } private static void menuItem_Unchecked(object sender, RoutedEventArgs e) { MenuItem menuItem = sender as MenuItem; if (menuItem == null) return; string groupName = GetOptionGroupName(menuItem); if (groupName == null) return; // 0 checked option is allowed if (groupName.EndsWith("*") || groupName.EndsWith("?")) return; var group = GetOptionGroup(menuItem, false); if (group == null) return; if (!group.Any(item => item.IsChecked)) menuItem.IsChecked = true; } } }