2017-02-02 2 views
0

У меня есть User Control с редактором String Collection, в котором я сохраняю список имен табуляции следующим образом:проверить, есть ли изменения в System.Windows.Forms.Design.StringCollectionEditor, чтобы вызвать событие изменения свойства PropertyGalue в C# Winforms

[Editor(@"System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a", typeof(System.Drawing.Design.UITypeEditor))] 
    public List<string> TabPages { 
     get {return tabpages;} 
     set { 
      tabpages = value; 
     } 
    } 

Эта функция служит также представляется как и в свойстве сетки:

enter image description here

Я хочу знать, как можно знать, если изменение произошло в коллекции.

Проблема, с которой я сталкиваюсь, заключается в том, что, хотя изменения в коллекции сохраняются после сохранения изменений, я не знаю, как написать событие, чтобы проверить, изменилась ли эта коллекция.

Для свойства как BackColor, я в состоянии обнаружить изменения, как так:

 if (e.ChangedItem != null && e.ChangedItem.Label == "BackColor" && ((Color)e.ChangedItem.Value).ToArgb() == Color.Transparent.ToArgb()) {  
        e.ChangedItem.PropertyDescriptor.SetValue(propertyGrid1.SelectedObject, e.OldValue); 
     } 

в функции:

private void propertyGrid1_PropertyValueChanged(object s, PropertyValueChangedEventArgs e); 

, что связано с моим PropertyGrid так:

this.propertyGrid1.PropertyValueChanged += new System.Windows.Forms.PropertyValueChangedEventHandler(this.propertyGrid1_PropertyValueChanged); 

Однако с коллекцией изменение в StringCollectionEditor не обнаружен в этом же процессе.

enter image description here

Есть специальный EventHandler, связанный с StringCollecitonEditor, что мне нужно, чтобы подписаться на? или, возможно, есть какой-то способ изменить декларацию.

Буду благодарен за любую помощь в этом направлении.

[Изменено]

Мои ограничения:

  1. я использую VS 2010 с точкой чистого 3,5. мой проект должен оставаться в dot net 3.5, потому что все наши решения требуют обратной совместимости с этой версией.
+0

Я нашел [это] (https://social.msdn.microsoft.com/Forums/windows/en-US/571fcee9-652b-43a0-b71e-b3ab956f388d/propertygrid-collection-editing-how- can-i-know-when-collection-was-changed? forum = winformsdatacontrols), вы можете попробовать использовать наблюдаемую коллекцию (тогда у вас будет событие), или вы всегда можете сделать собственный редактор. Что касается 'PropertyValueChanged', то причины, по которым он не запускается, потому что вы не меняете значение этого свойства (' PropertyGrid' позволяет вам редактировать свойство только для getter). – Sinatr

+0

Я не могу изменить его на наблюдаемый коллектив в моем случае, это всего лишь список строк, к которым я позже связываю свои свойства во время выполнения. Не уверен, смогу ли я сделать пользовательский редактор во времени :( –

+0

Являются ли какие-либо события запущенными после закрытия StringCollectionEditor? Я ищу механизм, который затем может вызывать внешнее событие PropertyGalal Property Property объекта PropertyGalue –

ответ

1

Одним из возможных вариантов является перехват StringCollectionEditor, для этого вы должны создать собственный редактор, как показано ниже:

class MyEditor : UITypeEditor 
{ 
    public override UITypeEditorEditStyle GetEditStyle(ITypeDescriptorContext context) 
    { 
     return UITypeEditorEditStyle.Modal; 
    } 
    public override object EditValue(ITypeDescriptorContext context, IServiceProvider provider, object value) 
    { 
     var type = Type.GetType(@"System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); 
     dynamic editor = Activator.CreateInstance(type, new[] { typeof(UITypeEditor) }); 
     var result = editor.EditValue(context, provider, value); 
     // call your event here 
     return result; 
    } 
} 

Используйте его как этот

[Editor(typeof(MyEditor), typeof(UITypeEditor))] 
public List<string> TabPages { get; } = new List<string>(); 

Edit: выше код работающий на VS2015 (dynamic и автоисторический инициализатор), в противном случае вам, возможно, придется использовать отражение и полное свойство:

readonly List<string> _tagPages = new List<string>(); 
[Editor(typeof(MyEditor), typeof(UITypeEditor))] 
public List<string> TabPages { get { return _tabPages; } } 

// reflection part 
var type = Type.GetType(@"System.Windows.Forms.Design.StringCollectionEditor, System.Design, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a"); 
var editor = Activator.CreateInstance(type, new[] { typeof(UITypeEditor) }); 
var method = type.GetMethod(nameof(EditValue), new[] { typeof(ITypeDescriptorContext), typeof(IServiceProvider), typeof(object) }); // if nameof is also missing then just use "EditValue" in place of it 
var result = method.Invoke(editor, new[] { context, provider, value }); 
+0

. = editor.EditValue (контекст, поставщик, значение); 'отправляет сообщение об ошибке« Предопределенный тип «Microsoft.CSharp.RuntimeBinder.Binder» не определен или не импортируется », поскольку я использую VS 2010 и .net 3.5. –

+0

Это из-за 'dynamic'? Я использую его, чтобы избежать использования рефлексии явно для вызова метода EditValue() с параметрами, см. [этот ответ] (http://stackoverflow.com/a/ 3110313/1997232). – Sinatr

+0

Чтобы быть откровенным, я очень новичок в C# и не знаю, что такое отражение. Позвольте мне посмотреть, поможет ли ваше предложение решить проблему. –

Смежные вопросы