#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.
Я надеюсь, вам понравится
Люк