C# 事件,用于同步使用相同行为的所有控件
在我的WPF应用程序中,我有几个表单,为用户提供了大量的输入字段。事实证明,并非每个用户都需要依赖于其公司流程的所有字段,因此我有一个新的要求,允许用户根据自己的需要隐藏字段 我计划为此使用一个行为,它可以附加到基本上每个WPF控件。该行为将向每个控件添加一个上下文菜单,允许显示/隐藏所有可用字段。我当前的测试项目似乎工作得很好,它有四个从属属性来确保一切正常工作:C# 事件,用于同步使用相同行为的所有控件,c#,.net,wpf,behavior,attachedbehaviors,C#,.net,Wpf,Behavior,Attachedbehaviors,在我的WPF应用程序中,我有几个表单,为用户提供了大量的输入字段。事实证明,并非每个用户都需要依赖于其公司流程的所有字段,因此我有一个新的要求,允许用户根据自己的需要隐藏字段 我计划为此使用一个行为,它可以附加到基本上每个WPF控件。该行为将向每个控件添加一个上下文菜单,允许显示/隐藏所有可用字段。我当前的测试项目似乎工作得很好,它有四个从属属性来确保一切正常工作: 字符串VisibilityGroupName: 它以某种方式充当每个字段的Id,但不是唯一的,以便将多个字段分组在一起(例如,将字
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Interactivity;
namespace CustomizableUserControlVisibility
{
public class WPFCustomVisibilityBehavior : Behavior<DependencyObject>
{
#region Fields
private Control _control = null;
private ContextMenu _contextMenu;
private bool _contextMenuIsBuilt = false;
#endregion
#region Properties
public bool NotificationDummy
{
get { return (bool)GetValue(NotificationDummyProperty); }
set { SetValue(NotificationDummyProperty, value); }
}
public static readonly DependencyProperty NotificationDummyProperty = DependencyProperty.Register("NotificationDummy", typeof(bool), typeof(WPFCustomVisibilityBehavior), new PropertyMetadata(false));
public bool AllowCustomVisibility
{
get { return (bool)GetValue(AllowCustomVisibilityProperty); }
set { SetValue(AllowCustomVisibilityProperty, value); }
}
public static readonly DependencyProperty AllowCustomVisibilityProperty = DependencyProperty.Register("AllowCustomVisibility", typeof(bool), typeof(WPFCustomVisibilityBehavior), new PropertyMetadata(false));
public string VisibilityGroupName
{
get { return (string)GetValue(VisibilityGroupNameProperty); }
set { SetValue(VisibilityGroupNameProperty, value); }
}
public static readonly DependencyProperty VisibilityGroupNameProperty = DependencyProperty.Register("VisibilityGroupName", typeof(string), typeof(WPFCustomVisibilityBehavior), new PropertyMetadata(string.Empty));
public Dictionary<string, bool> VisibilityDictionary
{
get { return (Dictionary<string, bool>)GetValue(VisibilityDictionaryProperty); }
set { SetValue(VisibilityDictionaryProperty, value); }
}
public static readonly DependencyProperty VisibilityDictionaryProperty = DependencyProperty.Register("VisibilityDictionary", typeof(Dictionary<string, bool>), typeof(WPFCustomVisibilityBehavior), new PropertyMetadata(new Dictionary<string, bool>()));
#endregion
#region Constructor
public WPFCustomVisibilityBehavior()
{
// TODO: There should be a better way to notify other controls about state changes than this...
var temp = DependencyPropertyDescriptor.FromProperty(WPFCustomVisibilityBehavior.NotificationDummyProperty, typeof(WPFCustomVisibilityBehavior));
if (temp != null)
{
temp.AddValueChanged(this, OnNotificationDummyChanged);
}
}
#endregion
#region Overrrides
protected override void OnAttached()
{
base.OnAttached();
if (this.AllowCustomVisibility == false)
{
return;
}
this._control = this.AssociatedObject as Control;
if (!string.IsNullOrEmpty(this.VisibilityGroupName) && this._control != null)
{
if (this.VisibilityDictionary.ContainsKey(this.VisibilityGroupName))
{
if (this.VisibilityDictionary[this.VisibilityGroupName])
{
this._control.Visibility = Visibility.Visible;
}
else
{
this._control.Visibility = Visibility.Collapsed;
}
}
else
{
this.VisibilityDictionary.Add(this.VisibilityGroupName, this._control.Visibility == Visibility.Visible ? true : false);
}
// Add a ContextMenu to the Control, but only if it does not already have one (TextBox brings its default ContextMenu for copy, cut and paste)
if (this._control.ContextMenu == null && !(this._control is TextBox))
{
this._contextMenu = new ContextMenu();
ContextMenuService.SetContextMenu(this._control, this._contextMenu);
this._control.ContextMenuOpening += (sender, e) => { ContextMenuOpening(e); };
}
}
}
#endregion
#region Event handling
private void ContextMenuOpening(ContextMenuEventArgs e)
{
if (this._contextMenuIsBuilt == false)
{
this._contextMenu.Items.Clear();
Dictionary<string, MenuItem> menuItems = new Dictionary<string, MenuItem>();
foreach (string k in this.VisibilityDictionary.Keys)
{
MenuItem menuItem = new MenuItem() { Header = k, Name = k, IsCheckable = true, StaysOpenOnClick = true };
menuItem.Click += MenuItem_Click;
menuItems.Add(k, menuItem);
}
var keyList = menuItems.Keys.ToList();
keyList.Sort();
foreach (string key in keyList)
{
this._contextMenu.Items.Add(menuItems[key]);
}
this._contextMenuIsBuilt = true;
}
foreach (MenuItem mi in this._contextMenu.Items)
{
mi.IsChecked = this.VisibilityDictionary[mi.Name];
}
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
MenuItem mi = sender as MenuItem;
if (mi != null && this.VisibilityDictionary != null && this.VisibilityDictionary.ContainsKey(mi.Name))
{
this.VisibilityDictionary[mi.Name] = mi.IsChecked;
// TODO: There should be a better way to notify other controls about state changes than this...
this.NotificationDummy = !NotificationDummy;
}
}
private void OnNotificationDummyChanged(object sender, EventArgs args)
{
// TODO: There should be a better way to notify other controls about state changes than this...
if (this._control != null && this.VisibilityDictionary != null && !string.IsNullOrEmpty(this.VisibilityGroupName))
{
if (this.VisibilityDictionary.ContainsKey(this.VisibilityGroupName))
{
if (this.VisibilityDictionary[this.VisibilityGroupName])
{
this._control.Visibility = Visibility.Visible;
}
else
{
this._control.Visibility = Visibility.Collapsed;
}
}
}
}
#endregion
}
}
使用系统;
使用System.Collections.Generic;
使用系统组件模型;
使用System.Linq;
使用系统文本;
使用System.Threading.Tasks;
使用System.Windows;
使用System.Windows.Controls;
使用System.Windows.Interactive;
命名空间可定制的SerControlVisibility
{
公共类WPFCustomVisibilityBehavior:行为
{
#区域字段
私有控制_Control=null;
私有上下文菜单\u上下文菜单;
私有bool_contextmenuisbuild=false;
#端区
#区域属性
公共广播通知
{
get{return(bool)GetValue(NotificationDummyProperty);}
set{SetValue(NotificationDummyProperty,value);}
}
public static readonly dependencProperty NotificationDummyProperty=dependencProperty.Register(“NotificationDummy”、typeof(bool)、typeof(WPFCustomVisibilityBehavior)、new PropertyMetadata(false));
公共布尔允许自定义可见性
{
get{return(bool)GetValue(AllowCustomVisibilityProperty);}
set{SetValue(AllowCustomVisibilityProperty,value);}
}
公共静态只读DependencyProperty AllowCustomVisibilityProperty=DependencyProperty.Register(“AllowCustomVisibility”、typeof(bool)、typeof(WPFCustomVisibilityBehavior)、new PropertyMetadata(false));
公共字符串可见性GroupName
{
get{return(string)GetValue(VisibilityGroupNameProperty);}
set{SetValue(VisibilityGroupNameProperty,value);}
}
公共静态只读DependencyProperty VisibilityGroupNameProperty=DependencyProperty.Register(“VisibilityGroupName”、typeof(string)、typeof(WPFCustomVisibilityBehavior)、new PropertyMetadata(string.Empty));
公共词典可视性词典
{
获取{return(Dictionary)GetValue(VisibilityDictionaryProperty);}
set{SetValue(VisibilityDictionaryProperty,value);}
}
公共静态只读DependencyProperty VisibilityDictionaryProperty=DependencyProperty.Register(“VisibilityDictionary”、typeof(Dictionary)、typeof(WPFCustomVisibilityBehavior)、new PropertyMetadata(new Dictionary());
#端区
#区域构造函数
公共WPFCustomVisibilityBehavior()
{
//TODO:应该有一种更好的方式来通知其他控件状态更改,而不是这样。。。
var temp=DependencyPropertyDescriptor.FromProperty(WPFCustomVisibilityBehavior.NotificationDummyProperty,typeof(WPFCustomVisibilityBehavior));
如果(温度!=null)
{
temp.AddValueChanged(此,OnNotificationDummyChanged);
}
}
#端区
#区域越界
受保护的覆盖无效附加()
{
base.onatached();
if(this.AllowCustomVisibility==false)
{
返回;
}
this.\u control=this.associated对象作为控件;
如果(!string.IsNullOrEmpty(this.VisibilityGroupName)&&this.\u控件!=null)
{
if(this.VisibilityDictionary.ContainsKey(this.VisibilityGroupName))
{
if(this.VisibilityDictionary[this.VisibilityGroupName])
{
这._control.Visibility=Visibility.Visible;
}
其他的
{
这._control.Visibility=Visibility.Collapsed;
}
}
其他的
{
this.VisibilityDictionary.Add(this.VisibilityGroupName,this.\u control.Visibility==Visibility.Visibility?true:false);
}
//将ContextMenu添加到控件中,但前提是该控件尚未添加ContextMenu(TextBox将其默认ContextMenu用于复制、剪切和粘贴)
if(this.\u control.ContextMenu==null&&!(this.\u控件是文本框))
{
这是._contextMenu=new contextMenu();
ContextMenuService.SetContextMenu(此._控件,此._contextMenu);
public class WPFCustomVisibilityBehavior : Behavior<DependencyObject>
{
#region Fields
public static event VisibilityChangedEventHandler OnVisibilityChanged;
private Control _control = null;
private ContextMenu _contextMenu;
private bool _contextMenuIsBuilt = false;
#endregion
#region Properties
public bool AllowCustomVisibility
{
get { return (bool)GetValue(AllowCustomVisibilityProperty); }
set { SetValue(AllowCustomVisibilityProperty, value); }
}
public static readonly DependencyProperty AllowCustomVisibilityProperty = DependencyProperty.Register("AllowCustomVisibility", typeof(bool), typeof(WPFCustomVisibilityBehavior), new PropertyMetadata(false));
public string VisibilityGroupName
{
get { return (string)GetValue(VisibilityGroupNameProperty); }
set { SetValue(VisibilityGroupNameProperty, value); }
}
public static readonly DependencyProperty VisibilityGroupNameProperty = DependencyProperty.Register("VisibilityGroupName", typeof(string), typeof(WPFCustomVisibilityBehavior), new PropertyMetadata(string.Empty));
public Dictionary<string, bool> VisibilityDictionary
{
get { return (Dictionary<string, bool>)GetValue(VisibilityDictionaryProperty); }
set { SetValue(VisibilityDictionaryProperty, value); }
}
public static readonly DependencyProperty VisibilityDictionaryProperty = DependencyProperty.Register("VisibilityDictionary", typeof(Dictionary<string, bool>), typeof(WPFCustomVisibilityBehavior), new PropertyMetadata(new Dictionary<string, bool>()));
#endregion
#region Constructor
public WPFCustomVisibilityBehavior()
{
OnVisibilityChanged += VisibilityChanged;
}
#endregion
#region Overrrides
protected override void OnAttached()
{
base.OnAttached();
if (this.AllowCustomVisibility == false)
{
return;
}
this._control = this.AssociatedObject as Control;
if (!string.IsNullOrEmpty(this.VisibilityGroupName) && this._control != null)
{
if (this.VisibilityDictionary.ContainsKey(this.VisibilityGroupName))
{
if (this.VisibilityDictionary[this.VisibilityGroupName])
{
this._control.Visibility = Visibility.Visible;
}
else
{
this._control.Visibility = Visibility.Collapsed;
}
}
else
{
this.VisibilityDictionary.Add(this.VisibilityGroupName, this._control.Visibility == Visibility.Visible ? true : false);
}
}
// Add a ContextMenu to the Control, but only if it does not already have one (TextBox brings its default ContextMenu for copy, cut and paste)
if (this._control != null && this._control.ContextMenu == null && !(this._control is TextBox))
{
this._contextMenu = new ContextMenu();
ContextMenuService.SetContextMenu(this._control, this._contextMenu);
this._control.ContextMenuOpening += (sender, e) => { ContextMenuOpening(e); };
}
}
#endregion
#region Event handling
private void ContextMenuOpening(ContextMenuEventArgs e)
{
if (this._contextMenuIsBuilt == false)
{
// Clear Items just to be sure there is nothing in it...
this._contextMenu.Items.Clear();
// Create default items first
MenuItem showAll = new MenuItem() { Header = "Show all optional fields", IsCheckable = false, FontWeight = FontWeights.Bold };
showAll.Click += MenuItem_ShowAll_Click;
MenuItem hideAll = new MenuItem() { Header = "Hide all optional fields", IsCheckable = false, FontWeight = FontWeights.Bold };
hideAll.Click += MenuItem_HideAll_Click;
// Create field items and sort them by name
Dictionary<string, MenuItem> menuItems = new Dictionary<string, MenuItem>();
foreach (string k in this.VisibilityDictionary.Keys)
{
MenuItem menuItem = new MenuItem() { Header = k, Name = k, IsCheckable = true, StaysOpenOnClick = true };
menuItem.Click += MenuItem_Click;
menuItems.Add(k, menuItem);
}
var keyList = menuItems.Keys.ToList();
keyList.Sort();
// Now add default items followed by field items
this._contextMenu.Items.Add(showAll);
this._contextMenu.Items.Add(hideAll);
this._contextMenu.Items.Add(new Separator());
foreach (string key in keyList)
{
this._contextMenu.Items.Add(menuItems[key]);
}
this._contextMenuIsBuilt = true;
}
foreach (Object o in this._contextMenu.Items)
{
MenuItem mi = o as MenuItem;
if (mi != null && mi.FontWeight != FontWeights.Bold)
{
mi.IsChecked = this.VisibilityDictionary[mi.Name];
}
}
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
MenuItem mi = sender as MenuItem;
if (mi != null && this.VisibilityDictionary != null && this.VisibilityDictionary.ContainsKey(mi.Name))
{
this.VisibilityDictionary[mi.Name] = mi.IsChecked;
OnVisibilityChanged(this.VisibilityDictionary);
}
}
private void MenuItem_HideAll_Click(object sender, RoutedEventArgs e)
{
List<string> keys = this.VisibilityDictionary.Keys.ToList<string>();
foreach (string key in keys)
{
this.VisibilityDictionary[key] = false;
}
OnVisibilityChanged(this.VisibilityDictionary);
}
private void MenuItem_ShowAll_Click(object sender, RoutedEventArgs e)
{
List<string> keys = this.VisibilityDictionary.Keys.ToList<string>();
foreach (string key in keys)
{
this.VisibilityDictionary[key] = true;
}
OnVisibilityChanged(this.VisibilityDictionary);
}
private void VisibilityChanged(object visibilityDictionary)
{
if (this._control != null && this.VisibilityDictionary != null && this.VisibilityDictionary == visibilityDictionary && !string.IsNullOrEmpty(this.VisibilityGroupName))
{
if (this.VisibilityDictionary.ContainsKey(this.VisibilityGroupName))
{
if (this.VisibilityDictionary[this.VisibilityGroupName])
{
this._control.Visibility = Visibility.Visible;
}
else
{
this._control.Visibility = Visibility.Collapsed;
}
}
}
}
#endregion
}