2014-11-13 6 views
2

У меня возникла идея использовать пользовательские атрибуты для свойств в классе для целей привязки данных в интерфейсе winforms. Например, установка и изменение цвета backcolor, forecolor и tooltip в текстовом поле с недопустимыми данными. Я обнаружил, что могу связать свойства управления txtTest для backcolor и т. Д. С таким настраиваемым атрибутом, как BackColorAttr, украшающим свойство класса, такого как Name, без проблем. Само свойство value связано с текстом текстового поля, двусторонняя привязка которого работает очень хорошо, а исходная обратная сторона, forecolor и т. Д. Устанавливаются из начальных значений пользовательских атрибутов так, как я надеялся. Я делаю все это через класс BindingHelper, который сводит все кодировки к нескольким общим методам.vb.net изменение значений пользовательских атрибутов в классе

Где я нахожусь в тупике, это управление значениями пользовательских атрибутов позднее. Например, изменение обратного к красному. Ничто из того, что я пробовал, похоже, работает. Кто-нибудь пробовал что-то вроде этого или имел какие-то указания относительно того, как я могу продолжить?

+3

Можете ли вы показать, что вы пробовали до сих пор? – waka

+0

Атрибуты ваших свойств доступны только для чтения. Даже если вы можете изменить их во время выполнения, они не будут поддерживать интерфейс INotifyPropertyChanged, поэтому ваша привязка никогда не обновит значения, привязанные к этим атрибутам. – Steve

+0

@Steve: это WinForms, поэтому интерфейс INotifyPropertyChanged не является, по крайней мере, изначально. –

ответ

0

Я не совсем следую первой части, или какое обязательство имеет отношение к цветам или атрибутам, но это не так, как работает Attributes. Они не являются обертками свойств и Properties, Methods и Types не имеют отношения к связанным с ними связанным с ними Attributesнаоборот). Это метаданные, собранные в сборку. Таким образом, вы не можете изменить значение каким-либо значимым образом.

Класс испытаний и тестирования Атрибут:

Public Class BarState 
    Inherits Attribute 

    Public Property State As String 

    Public Sub New(t As String) 
     State = t 
    End Sub 
End Class 

Public Class Foo 

    <BarState("red")> 
    Public Property Name As String 

End Class 

С State это свойство, испытание, если мы можем установить его:

Dim f As New Foo 

' get props for the Type 
Dim pi As PropertyInfo = f.GetType.GetProperty("Name") 

Dim attr = pi.GetCustomAttributes(GetType(BarState), False) 

If attr.Length > 0 Then 
    ' get prop info for the State property on the Attr Type 
    Dim pa As PropertyInfo = attr(0).GetType.GetProperty("State") 
    ' change it 
    CType(attr(0), BarState).State = "GREEN" 
    ' or 
    'pa.SetValue(attr(0), "GREEN", Nothing) 

    ' print it (prints "GREEN" but it does not persist) 
    Console.WriteLine(CType(attr(0), BarState).State) 
End If 

'get the attr again as you might do next time thru 
attr = pi.GetCustomAttributes(GetType(BarState), False) 
' print the value (Print "red") 
Console.WriteLine(CType(attr(0), BarState).State) 

Первая печать будет «GREEN», но это только для этот экземпляр - он не сохраняется. В следующий раз, когда вы его получите, он вернется к «красному». Поскольку атрибут is a Тип, мы можем попробовать Reflection, чтобы изменить значение, используя pa.SetValue(attr(0), "GREEN", Nothing), который закомментирован. Он по-прежнему сохраняется, потому что «красный» скомпилирован в сборку, что и будет вашей отправной точкой.

Может показаться, что вы можете хранить словарь или коллекцию экземпляров атрибутов для всех свойств для всех типов. Это может сработать, за исключением того, что все они похожи друг на друга, поэтому вам нужно будет создать хеш для отслеживания того, что Attribute экземпляр идет с тем, что Property на что Type.

И вам придется синхронизировать эту коллекцию с основными объектами экземпляра. Экземпляр Attribute не знает, что экземпляр, из которого он пришел, исчез, и поэтому параметр состояния должен вернуться, поэтому вашему менеджеру атрибутов нужно будет это обработать.


Вы можете посмотреть в «ткачей», использование которых атрибуты помечать вещи (например, диапазон значений), а затем переписать сборку плести чеками диапазона для помеченных свойств. Похоже на то, что вы после, я не знаю, что еще они могут сделать в соответствии с тем, что вы описываете.

+0

ОК, спасибо, ребята. Похоже, я просил кирпич плавать, LOL. Плутоникс, я на самом деле сделал что-то похожее на то, что вы предлагаете, в VB6, давно. Использование созданных наборов записей для хранения материалов интерфейса, а затем манипулирование интерфейсом с этими значениями. Работал отлично, весь код был инкапсулирован, yada yada yada. Поскольку часть этой работы включала определение атрибутов управления, которые я хотел манипулировать, я надеялся сделать что-то подобное в .NET, просто без всякой работы. :-) – ncscoots

+0

Посмотрите на ткачей, таких как [Fody] (https://github.com/Fody/PropertyChanged), которые предоставляют уведомление об изменении свойства. Это обеспечило бы событие, в котором вы могли бы сделать многое из того, что хотите. Существует также коммерческая версия с бесплатной версией. – Plutonix

+0

также, если это прояснить ситуацию, вы должны нажать галочку, чтобы отменить это [список без ответа] (http://stackoverflow.com/help/someone-answers) – Plutonix