【问题标题】:Component Communication at Design Time设计时的组件通信
【发布时间】:2011-04-22 10:39:46
【问题描述】:

我想要一个“form”或其他可以将字符串添加到列表的东西(无论如何)

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

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

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

我不知道如何告诉“ComponentReader”他所指的主要组件在哪里,

(我在“ComponentReader”中添加了属性ReferedStringManager)。

是否有任何属性或指令(或方式)来检查项目和他的references以获取所有匹配值作为“列表” ComponentReader" 属性 对于ComponentReaderReferedStringManager 属性;

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

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

【问题讨论】:

  • 也许您应该备份并解释您提出的“解决方案”旨在解决的问题。可能是有另一种方法来解决原来的问题。
  • 我只是想知道我是否可以做到这一点......以及如何做到这一点,也许不止一种解决方案......

标签: c# winforms


【解决方案1】:

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

StringManager 和 ComponentReader 类都有很多要求。

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

2) StringManager 必须覆盖 Component 类的 Site 属性。这就是让它“感知 VS 设计器”的原因,并允许稍后在 ComponentReader 的属性中选择它。

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

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

5) ComponentReader 必须具有 StringManager 类型的公共属性

6) ComponentReader 必须具有用于 SelectedString 的字符串类型的公共属性。问题是我们必须将 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 窗体项目,将这些文件添加到其中,然后构建项目。

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

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

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

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

希望你喜欢

卢克

【讨论】:

    猜你喜欢
    • 2018-09-14
    • 2012-10-25
    • 1970-01-01
    • 2016-06-17
    • 2017-06-25
    • 1970-01-01
    • 2010-10-14
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多