2015-01-22 5 views
0

У меня есть веб-формы WebUserControl, который имеет логическое свойство ShowAccessLevels:Как выполнить внутреннюю логику, когда UserControl значение свойства изменяется

Public Property ShowAccessLevels As Boolean 
    Get 
     Dim a As Object = ViewState("_ShowAccessLevels") 
     If a Is Nothing Then 
      a = False 
     End If 
     Return Convert.ToBoolean(a) 
    End Get 
    Set(value As Boolean) 
     ViewState("_ShowAccessLevels") = value 
    End Set 
End Property 

Когда сеттер вызывается, если значение изменилось, мне нужно выполнить некоторую внутреннюю логику, чтобы показать/скрыть поля на основе значения:

Private Sub ShowAccessLevelsChanged() 
    If value = False Then 
     ' do stuff here 
    Else 
     ' do stuff here 
    End If 
End Sub 

Я знаю, что я могу вызвать метод из сеттеров, но я не уверен в том, что это лучшая практика:

Set(value As Boolean) 
    If ViewState("_ShowAccessLevels") <> value Then 
     ViewState("_ShowAccessLevels") = value 
     ShowAccessLevelsChanged() 
End Set 

Мне понадобятся методы для многих разных свойств, поэтому создание нового каждый раз становится неуклюжим. Я вижу, что раньше задавали вопрос similar question, но я не могу понять, соответствует ли окончательное решение тому, что советуют эксперт и this MSDN article.

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

Если я реализую INotifyPropertyChanged тогда я в конечном итоге с этими дополнениями, но не может работать, как связать логику с моей собственности:

Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) Implements INotifyPropertyChanged.PropertyChanged 

Private Sub NotifyPropertyChanged(<CallerMemberName()> Optional ByVal propertyName As String = Nothing) 
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) 
End Sub 

Я бы признателен за любые указатели пожалуйста.

+2

'INotifyPropertyChanged' будет работать так же, как и альтернативный набор. Когда 'value <> _ShowAccessLevels' вы поднимете событие. Если подписчиков на мероприятие нет, он ничего не решит. Я могу показать, как его реализовать, но у вас будет одинаковый код в каждом сеттере, и он будет не менее «неуклюжим», чем тот, который у вас есть. Вопрос заключается в том, есть ли что-то, кто подписывается, возможно, предсказывает вызов ViewState. – Plutonix

+0

Хорошо, что прояснение - это все, что я искал, в отсутствие решения, которое отличалось от того, что я сделал. Спасибо. – EvilDr

+0

, вы можете использовать аналогичную * структуру * для обработки изменений, полученных в результате реквизита, а не для отдельной процедуры для каждого из них. – Plutonix

ответ

1

не может работать, как связать логику с моей собственностью ... Я бы признателен за любые указатели, пожалуйста

INotifyPropertyChanged будет работать немного, как вы могли бы использовать ShowAccessLevelsChanged за исключением более общей форме:

Set(value As Boolean) 
    If _AccessLevel <> value Then 
     _AccessLevel = value 
     RaiseEvent PropertyChanged(Me, 
      New PropertyChangedEventArgs("AccessLevel ")) 

    End If 
End Set 

INotifyPropertyChanged чаще всего используется для уведомления что-то внешний который изменил значение свойства. Например, BindingList(Of T), используемый в качестве DataSource, будет наблюдать за событием PropertyChanged и обновлять элемент управления в результате.

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

Set(value As Boolean) 
    If (value <> _ShowAccessLevels) Then 
     _ShowaccessLevels = value 
     UpdateForChange() 
    End If 
End Set 

Private Sub UpdateForChange(<CallerMemberName> Optional propname As String = "") 
    Select Case propname 
     Case "FooVisible" 
      Me.Foo.Visible = FooVisible ' a simple change 

     Case "Bar" 
      BuildBarList(Me.Bar)   ' more involved 

     Case "ShowAccessLevel" 
      UpdateAccess(Me.AccessLevel) ' very involved (?) 
     ... 
  • Частного событие ничего не добавляет к соединению для местного уведомления. Поднятие события, так что локальный обработчик может вызвать другой метод, является жестким, когда вы можете напрямую вызвать локальную процедуру.
  • Простые изменения могут быть обработаны непосредственно в процедуре или могут вызвать специализированные помощники, когда изменение прокрутки включает в себя множество строк кода.
  • Нет необходимости проходить value, так как это будет связано с боксом и еще нелепостью. В качестве локальной процедуры доступны как свойства, так и поля поддержки напрямую.
  • Также исходный код, похоже, объединяет имена полей поддержки с именами свойств: особенно внешние субъекты могут не связывать FooBar с _FooBar.
  • Нет необходимости передавать имя свойства, которое изменилось: приведенное выше показывает, используя <CallerMemberName>, который передаст имя вызывающего члена обновлению. Это то же самое, что и UpdateForChange("Foo"), но не вводите ошибку, если вы вставляете ее в другой сеттер. Он требует NET 4.5 и импортирует System.Runtime.CompilerServices, но может очень хорошо работать без него.
  • Если задействовано большинство реакций, каждый сеттер может называть отдельных специализированных помощников. По-прежнему нет причин помещать и пропускать value или даже пропущенное, поэтому коэффициент кланов все еще уменьшается.

Обычно в суб-классифицироваться управления, чтобы сделать что-то вроде этого, когда свойство как BackColor или ShowScrollBars изменений.

Не исключаю INotifyPropertyChanged еще

Это не значит, что ваше приложение не может извлечь выгоду из INotifyPropertyChanged. Код OP появляется, чтобы использовать ViewState, чтобы уведомить что-нибудь, где-то свойство изменилось. Ссылки в вопросе описывают, как следует использовать для этого INotifyPropertyChanged: - Этот класс будет реализовывать его как публичное событие и поднять его, когда изменяется поддержка, представляющая интерес для внешних участников. - Внешний класс добавит PropertyChanged обработчики событий и ответьте.

Вопрос конкретно задает вопрос о локальной обработке/уведомлении и исключает внешние уведомления (и не помечен для MV ??).

1

Это, как я хотел бы сделать это:

Implements INotifyPropertyChanged 

Public Event PropertyChanged(sender As Object, e As PropertyChangedEventArgs) _ 
    Implements INotifyPropertyChanged.PropertyChanged 

Private Sub NotifyPropertyChanged(<CallerMemberName()> Optional ByVal propertyName As String = Nothing) 
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(propertyName)) 
End Sub 

' Use a writable private backing field for your property. 
Private _accessLevels As Boolean = False 
Public Property AccessLevels As Boolean 
    Get 
     Return _accessLevels 
    End Get 
    Set(value As Boolean) 
     RefreshAccessLevels(value) 
    End Set 
End Property 

' Next create a method to refresh the property, or optionally pass it an 
' arbitrary value. Call the NotifyPropertyChanged method after updating. 
Public Sub RefreshAccessLevels(Optional ByVal newValue As Object = Nothing) 
    If newValue IsNot Nothing Then 
     _accessLevels = Convert.ToBoolean(newValue) 
    Else 
     newValue = ViewState("_ShowAccessLevels") 
     _accessLevels = If(newValue Is Nothing, False, Convert.ToBoolean(newValue)) 
    End If 
    NotifyPropertyChanged("AccessLevels") 
End Sub 

' Handle the PropertyChanged event if you need to refresh controls manually 
Private Sub HandlePropertyChanged(sender As Object, e As PropertyChangedEventArgs) Handles Me.PropertyChanged 
    Select Case e.PropertyName 
     Case "ShowAccessLevels" 
      ' Call some refresh logic here... 
     Case "SomeOtherProperty" 
      ' Etc... 
    End Select 
End Sub 

Таким образом, ваши связанные элементы управления обновляются должным образом после каждого обновления, и у вас есть только один метод, необходимый для обновления значения. В случае более обычного свойства с геттером и сеттером, а не с помощью Shoenanigans ViewState, вы просто вызываете NotifyPropertyChanged в своем сеттере без аргументов.

Private _accessLevels As Boolean = False 
Public Property AccessLevels As Boolean 
    Get 
     Return _accessLevels 
    End Get 
    Set(value As Boolean) 
     _accessLevels = value 
     NotifyPropertyChanged() 
    End Set 
End Property 

Атрибут CallerMemberName заботится о переадресации имя вызывающего участника к NotifyPropertyChanged метода.

Это, по сути, основная работа любой модели просмотра в MVVM и WPF. Определите класс, который реализует INotifyPropertyChanged, определите все ваши объекты данных, которые вам понадобятся для привязки данных, создайте экземпляр этой модели представления, привяжите ваше представление (форму) к свойству экземпляра и обновите свойства только с вашей модели (общий термин для программы. ..). Идея здесь заключается в разделении проблем. Вам никогда не придется обновлять свою форму напрямую через MVVM, форма обновляется в соответствии с состоянием модели представления.

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