【问题标题】:How to add validation to PropertyGrid's CollectionEditor?如何向 PropertyGrid 的 CollectionEditor 添加验证?
【发布时间】:2011-03-30 15:47:06
【问题描述】:

我正在使用 PropertyGrid 编辑包含集合的对象。 使用 CollectionEditor 编辑集合。 我必须确保集合中的元素是独一无二的。

如何向 CollectionEditor 添加验证:

  1. 通过重载 CollectionEditor 的 OnFormClosing
  2. 或者为创建/编辑项目添加验证?

【问题讨论】:

    标签: c# winforms propertygrid collectioneditor


    【解决方案1】:

    您可以创建自己的集合编辑器,并挂钩到默认编辑器控件上的事件。您可以使用这些事件来禁用“确定”按钮。比如:

    public class MyCollectionEditor : CollectionEditor
    {
        private static Dictionary<CollectionForm, Button> okayButtons 
            = new Dictionary<CollectionForm, Button>();
    
        // Inherit the default constructor from CollectionEditor
        public MyCollectionEditor(Type type) 
            : base(type) 
        {
        }
    
        // Override this method in order to access the containing user controls
        // from the default Collection Editor form or to add new ones...
        protected override CollectionForm CreateCollectionForm()
        {
            CollectionForm collectionForm = base.CreateCollectionForm();
            collectionForm.FormClosed += 
                new FormClosedEventHandler(collectionForm_FormClosed);
            collectionForm.Load += new EventHandler(collectionForm_Load);
    
            if (collectionForm.Controls.Count > 0)
            {
                TableLayoutPanel mainPanel = collectionForm.Controls[0] 
                    as TableLayoutPanel;
                if ((mainPanel != null) && (mainPanel.Controls.Count > 7))
                {
                    // Get a reference to the inner PropertyGrid and hook 
                    // an event handler to it.
                    PropertyGrid propertyGrid = mainPanel.Controls[5] 
                        as PropertyGrid;
                    if (propertyGrid != null)
                    {
                        propertyGrid.PropertyValueChanged += 
                            new PropertyValueChangedEventHandler(
                                propertyGrid_PropertyValueChanged);
                    }
    
                    // Also hook to the Add/Remove
                    TableLayoutPanel buttonPanel = mainPanel.Controls[1] 
                        as TableLayoutPanel;
                    if ((buttonPanel != null) && (buttonPanel.Controls.Count > 1))
                    {
                        Button addButton = buttonPanel.Controls[0] as Button;
                        if (addButton != null)
                        {
                            addButton.Click += new EventHandler(addButton_Click);
                        }
                        Button removeButton = buttonPanel.Controls[1] as Button;
                        if (removeButton != null)
                        {
                            removeButton.Click += 
                                new EventHandler(removeButton_Click);
                        }
                    }
    
                    // Find the OK button, and hold onto it.
                    buttonPanel = mainPanel.Controls[6] as TableLayoutPanel;
                    if ((buttonPanel != null) && (buttonPanel.Controls.Count > 1))
                    {
                        Button okayButton = buttonPanel.Controls[0] as Button;
                        if (okayButton != null)
                        {
                            okayButtons[collectionForm] = okayButton;
                        }
                    }
                }
            }
            return collectionForm;
        }
    
        private static void collectionForm_FormClosed(object sender, 
            FormClosedEventArgs e)
        {
            CollectionForm collectionForm = (CollectionForm)sender;
            if (okayButtons.ContainsKey(collectionForm))
            {
                okayButtons.Remove(collectionForm);
            }
        }
    
        private static void collectionForm_Load(object sender, EventArgs e)
        {
            ValidateEditValue((CollectionForm)sender);
        }
    
        private static void propertyGrid_PropertyValueChanged(object sender,
            PropertyValueChangedEventArgs e)
        {
            ValidateEditValue((CollectionForm)sender);
        }
    
        private static void addButton_Click(object sender, EventArgs e)
        {
            Button addButton = (Button)sender;
            ValidateEditValue((CollectionForm)addButton.Parent.Parent.Parent);
        }
    
        private static void removeButton_Click(object sender, EventArgs e)
        {
            Button removeButton = (Button)sender;
            ValidateEditValue((CollectionForm)removeButton.Parent.Parent.Parent);
        }
    
        private static void ValidateEditValue(CollectionForm collectionForm)
        {
            if (okayButtons.ContainsKey(collectionForm))
            {
                Button okayButton = okayButtons[collectionForm];
                IList<MyClass> items = collectionForm.EditValue as IList<MyClass>;
                okayButton.Enabled = MyCollectionIsValid(items);
            }
        }
    
        private static bool MyCollectionIsValid(IList<MyClass> items)
        {
            // Perform validation here.
            return (items.Count == 2);
        }
    
    }
    

    您还需要为您的收藏添加一个 Editor 属性:

    class MyClass
    {
      [Editor(typeof(MyCollectionEditor), 
              typeof(System.Drawing.Design.UITypeEditor))]
      List<Foo> MyCollection
      {
        get; set;
      }
    }
    

    注意:我发现 removeButton_Click 中项目的值不正确 - 因此可能需要进行一些调整。

    【讨论】:

    • 如何访问在函数collectionForm_FormClosing中编辑的集合项目? collectionForm.Items 受保护 :( 我需要检查项目的 name 属性是否唯一。
    • 你应该可以从 MyCollectionEditor 调用 this.GetItems() (虽然我自己没有尝试过)。
    • CollectionEditor 中确实有一个 GetItems() 函数,但是它有一个参数,这对我来说没有多大意义。 protected virtual Object[] GetItems( Object editValue ) 根据 MSDN:editValue - 要编辑的集合。非常冗长的文档。而从哪里获得收藏是首要的问题。 :(
    • 尝试使用 collectionForm.EditValue。这应该包含您的集合属性。
    • 确实,EditValue 包含集合。但是很少有其他问题弹出..设置e.Cancel = true后,集合项列表显示为空。再次按下 OK 按钮会导致 DialogResult.Cancel。这种验证方法有一些非常错误的地方。 :(
    【解决方案2】:

    尝试 collectionForm.Context.Instance 并将其类型转换为您的数据类型,这应该可以解决问题。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-27
      • 2013-10-24
      • 1970-01-01
      • 2021-03-11
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多