设计时的组件通信

时间:2011-04-22 10:39:46

标签: c# winforms

我希望有一个“表单”或其他可以添加字符串到列表的内容(无论如何)

将使用包含字符串集合的第一个组件“StringManager”来完成

另一方面,我希望有另一个组件“ComponentReader”使用IExtenderProvider并在所有控件(在组件表单上)添加一个名为“TheString”的属性,它允许我从其中一个字符串中选择列表

所以,要明确:我希望与每个表单上的最少代码共享List<String>,(最多使用属性编辑器)

我不知道怎么能告诉“ComponentReader”他所指的主要成分在哪里,

(我在“ReferedStringManager”中添加了一个属性ComponentReader

是否有任何属性或指示(或方式)检查项目及其引用以将所有匹配值作为列表中的“ ComponentReader“属性 对于ReferedStringManager;

ComponentReader属性

如果不可能,我会想到静态列表或其他东西,也许是XML文件,(但我不知道如何在构思期间管理它)

当然所有这些都是在设计时,而不是在执行时间(它会更简单!!)

1 个答案:

答案 0 :(得分:1)

这是一个迟到的答案,但如果你仍然感兴趣,这里是如何做到的。

对于StringManager和ComponentReader类,有很多要求。

1)两个类都需要从System.ComponentModel.Component派生。

2)StringManager必须覆盖Component类的Site属性。这使它成为“VS Designer aware”,并允许它稍后在ComponentReader的属性中进行选择。

3)StringManager必须将List公开为公共属性。为方便起见,在我的示例代码bolow中,我在VS属性网格中设置了EditorAttribute以便于字符串集合版本。

4)ComponentReader必须实现只有一个StringManager类型属性的自定义接口。这是需求#6所需要的。

5)ComponentReader必须具有StringManager

类型的公共属性

6)ComponentReader必须具有SelectedString类型为string的公共属性。问题是我们必须将TypeConverterAttribute设置为另一个我们必须实现的类(参见#7)

7)我们必须实现StringConverter派生类。这将用于允许我们从选定的StringManager中选择一个字符串。在这个类中,我们必须能够通过在#4中创建的接口检索对ComponentReader的引用。

现在,代码:

StringManager.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;
using System.Windows.Forms;
using System.ComponentModel.Design;

namespace VSDesignHost
{
class StringManager : Component
{
    private ContainerControl _containerControl = null;

    public StringManager()
    {
        TheList = new List<string>();
    }

    public StringManager(IContainer container) : this()
    {
        container.Add(this);

        InitializeComponent();
    }

    private void InitializeComponent()
    {
        //Whatever
    }

    public ContainerControl ContainerControl
    {
        get { return _containerControl; }
        set { _containerControl = value; }
    }

    public override ISite Site
    {
        set
        {
            base.Site = value;
            if (value != null)
            {
                IDesignerHost host = value.GetService(typeof(IDesignerHost)) as IDesignerHost;
                if (host != null)
                {
                    IComponent rootComponent = host.RootComponent;
                    if (rootComponent is ContainerControl)
                    {
                        this.ContainerControl = (ContainerControl)rootComponent;
                    }
                }
            }
        }
    }

    [Editor("System.Windows.Forms.Design.StringCollectionEditor, System.Design", "System.Drawing.Design.UITypeEditor, System.Drawing")]
    public List<string> TheList { get; set; }

}
}

ComponentReader.cs

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace VSDesignHost
{
    class ComponentReader : Component, IStringManagerEnabled
    {
        private StringManager sm;

        public ComponentReader()
        {
            sm = null;
        }

        [Browsable(true), Category("MyCategory")]
        public StringManager StringManager
        {
            get { return sm; }
            set
            {
                sm = value;
            }
        }

        [Browsable(true), Category("MyCategory"), TypeConverter(typeof(StringManagerStringConverter))]
        public string SelectedString { get; set; }

    }
}

IStringManagerEnabled.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace VSDesignHost
{
    interface IStringManagerEnabled
    {
        StringManager StringManager
        {
            get;
            set;
        }
    }
}

StringManagerStringConverter.cs:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.ComponentModel;

namespace VSDesignHost
{
    class StringManagerStringConverter : StringConverter
    {
        #region Make It A ComboBox
        public override bool GetStandardValuesSupported(ITypeDescriptorContext context)
        {
            return true;
        }
        public override bool GetStandardValuesExclusive(ITypeDescriptorContext context)
        {
            return false;
        }
        #endregion


        #region Display Tags In List
        public override StandardValuesCollection GetStandardValues(ITypeDescriptorContext context)
        {
            if ((context == null) || (context.Container == null))
            {
                return null;
            }

            Object[] Tags = this.GetTagsFromServer(context);
            if (Tags != null)
            {
                return new StandardValuesCollection(Tags);
            }
            return null;
        }

        private object[] GetTagsFromServer(ITypeDescriptorContext context)
        {
            List<string> availableTags = new List<string>();

            if (context.Instance == null)
            {
                availableTags.Add("ITypeDescriptorContext.Instance is null");
                return availableTags.ToArray();
            }


            IStringManagerEnabled inst = context.Instance as IStringManagerEnabled;
            if (inst == null)
            {
                availableTags.Add(context.Instance.ToString());
                return availableTags.ToArray();
            }

            if (inst.StringManager == null)
            {
                availableTags.Add("No StringManager selected");
                return availableTags.ToArray();
            }

            availableTags = inst.StringManager.TheList;
            availableTags.Sort(Comparer<string>.Default);
            return availableTags.ToArray();
        }

        #endregion



        public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
        {
            if (sourceType == typeof(string))
                return true;
            return base.CanConvertFrom(context, sourceType);
        }

        public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
        {
            if (value is string)
                return value.ToString();
            return base.ConvertFrom(context, culture, value);
        }

    }
}

创建Windows窗体项目,将这些文件添加到其中,然后构建项目。

现在,在Form上,您可以通过从工具箱中拖动来添加每个StringManager和ComponentReader的实例。

选择StringManager,并在属性中,使用字符串集合编辑器向TheList添加一些字符串。

选择ComponentReader,在属性窗口中,您应该能够从下拉列表中选择StringManager实例。

您现在应该可以从SelectedString的下拉列表中选择一个字符串。

我希望你喜欢

吕克