Взаимодействие компонентов во время разработки

#c# #winforms

#c# #winforms

Вопрос:

Я хочу иметь «форму» или что-то еще (неважно что), которое может добавлять строку в список

это было бы сделано с помощью первого компонента « StringManager «, который содержит коллекцию строк

С другой стороны, я хочу иметь другой компонент « ComponentReader «, который использует IExtenderProvider и добавляет ко всем элементам управления (в форме компонента) свойство с именем «theString», которое позволяет мне выбирать в одной из строк из списка

Итак, чтобы внести ясность: я хочу поделиться List<String> минимальным количеством кода для каждой формы (больше всего с редактором свойств)

Я не знаю, как я могу определить « ComponentReader «, где находится основной компонент, на который он ссылается,

(я добавил свойство ReferedStringManager в свой « ComponentReader «).

Существуют ли какие-либо свойства или инструкции (или способ)для проверки проекта и его ссылок, чтобы получить все подходящие значения в виде списка в « ComponentReader » свойствах для ReferedStringManager свойства ComponentReader ;

Если это невозможно, я думаю о статическом списке или чем-то другом, возможно, XML-файле, (но я не знаю, как управлять этим во время разработки)

Конечно, все это происходит во время разработки, а не во время выполнения (это было бы так проще !!)

Комментарии:

1. Возможно, вам следует создать резервную копию и объяснить проблему, для решения которой предназначено ваше предлагаемое «решение». Возможно, есть другой способ решить исходную проблему.

2. я просто хочу узнать, смогу ли я это сделать… и как это сделать, возможно, более одного решения…

Ответ №1:

это поздний ответ, но если вам все еще интересно, вот как это сделать.

Существует довольно много требований как к вашему StringManager, так и к вашим классам ComponentReader.

1) оба класса должны быть производными от System.ComponentModel.Компонент.

2) StringManager должен переопределить свойство Site класса Component. Это то, что делает его «совместимым с разработчиком» и позволяет позже выбирать его в свойствах вашего ComponentReader.

3) StringManager должен предоставлять список как общедоступное свойство. Для удобства, в моем примере кода ниже, я установил атрибут EditorAttribute для easy string collection edition в таблице свойств VS.

4) Программа ComponentReader должна реализовать пользовательский интерфейс только с одним свойством типа StringManager. Это необходимо в соответствии с требованием # 6.

5) ComponentReader должен иметь общедоступное свойство типа StringManager

6) ComponentReader должен иметь общедоступное свойство типа string для выбранной строки. Загвоздка в том, что мы должны установить атрибут TypeConverterAttribute для еще одного класса, который мы должны внедрить (см. # 7)

7) Мы должны реализовать производный класс StringConverter. Это будет использоваться, чтобы позволить нам выбрать строку из выбранного StringManager. Внутри этого класса мы должны иметь возможность извлекать ссылку на ComponentReader через интерфейс, созданный в #4.

Теперь, что касается кода:

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 Forms, добавьте в него эти файлы и создайте проект.

Теперь в вашей форме вы можете добавить экземпляр каждого StringManager и ComponentReader, перетащив их из панели инструментов.

Выберите StringManager и в свойствах добавьте несколько строк в список, используя редактор коллекции строк.

Выберите ComponentReader, и в окнах свойств вы сможете выбрать свой экземпляр StringManager из выпадающего списка.

Теперь вы должны иметь возможность выбрать одну из строк из выпадающего списка для SelectedString.

Я надеюсь, вам понравится

Люк