Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/295.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 事件,用于同步使用相同行为的所有控件_C#_.net_Wpf_Behavior_Attachedbehaviors - Fatal编程技术网

C# 事件,用于同步使用相同行为的所有控件

C# 事件,用于同步使用相同行为的所有控件,c#,.net,wpf,behavior,attachedbehaviors,C#,.net,Wpf,Behavior,Attachedbehaviors,在我的WPF应用程序中,我有几个表单,为用户提供了大量的输入字段。事实证明,并非每个用户都需要依赖于其公司流程的所有字段,因此我有一个新的要求,允许用户根据自己的需要隐藏字段 我计划为此使用一个行为,它可以附加到基本上每个WPF控件。该行为将向每个控件添加一个上下文菜单,允许显示/隐藏所有可用字段。我当前的测试项目似乎工作得很好,它有四个从属属性来确保一切正常工作: 字符串VisibilityGroupName: 它以某种方式充当每个字段的Id,但不是唯一的,以便将多个字段分组在一起(例如,将字

在我的WPF应用程序中,我有几个表单,为用户提供了大量的输入字段。事实证明,并非每个用户都需要依赖于其公司流程的所有字段,因此我有一个新的要求,允许用户根据自己的需要隐藏字段

我计划为此使用一个行为,它可以附加到基本上每个WPF控件。该行为将向每个控件添加一个上下文菜单,允许显示/隐藏所有可用字段。我当前的测试项目似乎工作得很好,它有四个从属属性来确保一切正常工作:

  • 字符串VisibilityGroupName:
  • 它以某种方式充当每个字段的Id,但不是唯一的,以便将多个字段分组在一起(例如,将字段标题的标签添加到相应的文本框)。此字符串当前还用作用户在上下文菜单中看到的名称

  • 字典可见性字典:
  • 此词典跟踪字段的所有可见性状态。在我的应用程序中,我将把它序列化为XML,以使用户的决策持久化

  • 布尔允许自定义可见性:
  • 这只是一个用来关闭整个功能的标志

  • bool NotificationDummy:
  • 这就是它变得有趣的地方。目前,我将此属性与ValueChanged事件一起滥用,以通知所有控件状态已更改,以便它们可以检查是否受到影响。虽然这是预期的效果,但我知道这只是一个糟糕的解决方法,因为我不知道如何正确地完成通知

    有人知道如何正确地做吗?我已经用TODO标记了代码中的相应位置:

    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
    }