Управление управляемой событиями навигацией в приложении WPF - PullRequest
0 голосов
/ 12 ноября 2011

Я думаю, что название этого вопроса, вероятно, неверно, но я не совсем понимаю, как его сформулировать. У меня есть приложение CF 4.0 (VS2010) WPF.

Это приложение состоит из одного окна с заголовком, включающим основы (логотипы, подписи и т. Д.) И набор кнопок навигации (назад, повтор, далее и т. Д.). Остальная часть окна состоит из списка, заполненного одним или несколькими пользовательскими элементами управления в зависимости от того, в каком режиме находится приложение в данный момент.

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

Например, один экран - это экран конфигурации, и в списке есть три пользовательских элемента управления. Эти элементы управления являются пользовательскими классами, которые наследуются от UserControl. Кроме того, они реализуют интерфейс, который определяет метод 'bool Validate', который определяет, полностью ли заполнен элемент управления.

Этот же сценарий может применяться ко многим другим ситуациям, но это общий вариант использования, который довольно прост для понимания. Когда экран первоначально загружает кнопку «Далее», видимость которой контролируется родительским окном, он виден, но отключен, поскольку дочерние элементы управления еще не могут быть действительными. В какой-то момент, когда пользователь заполняет произвольные данные в одном или нескольких элементах управления, каждый из них возвращает true, если вызывается его метод Validate.

В тот момент, когда все элементы управления действительны, следующая кнопка станет активной. Довольно простой дизайн.

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

Я думаю, что событие изменения каждого элемента управления в UserControl (текстовые поля, переключатели и т. Д.) Будет вызывать триггер частное событие проверки, и это установит некоторое открытое свойство в интерфейсе или классе.

f Могу ли я сделать так, чтобы родительское окно могло реагировать на изменение этого свойства управляемым событиями образом? Я не собираюсь делать это в WPF, делать это в коде на C # предпочтительнее, поскольку я пока не хочу вдаваться в сложность WPF. Я просто не уверен, кроме постоянного опроса, как определить, когда свойство IsValid каждого элемента управления синхронизирует все со значением true, если это даже хороший подход.


EDIT:

Хорошо, вот еще один способ задать вопрос. У меня есть список чего-либо (в данном случае список интерфейса), и я хочу иметь возможность реагировать на изменение общедоступных свойств для каждого элемента в списке, чтобы я мог выполнить действие, когда все элементы есть (в данном случае bool) правда. Выше объясняется вариант использования, но это более общая версия вопроса.


EDIT:

@ Vincent "вы можете сделать это еще проще с помощью пользовательского события" ValidatedChanged () ", которое вы можете подключить таким же образом."

Оказывается, это действительно то, что я искал. Подход к уведомлению о свойствах более удобен для использования с элементами управления с привязкой к данным. Я прочитал много постов на этом сайте о том, как это реализовать, но на самом деле это было не то, что я хотел. Я просто хотел, чтобы мои объекты уведомляли о том, что произошло событие, которое оказалось изменением свойства, но это не относится к делу. Я нашел документацию по реализации события в интерфейсе, и теперь он работает. Спасибо за то, что указали мне правильное направление и помогли мне понять, что на самом деле мне нужно.

1 Ответ

1 голос
/ 12 ноября 2011

Итак, у вас есть ListBox, который содержит все ваши элементы управления, и когда все элементы управления проверены, кнопка Next должна быть включена?Если это так, когда один из ваших элементов управления проверяет, вы можете искать всех сыновей ListBox, чтобы проверить их на предмет проверки, используя VisualTreeHelper.GetChildren, чтобы получить их все.Если вы не хотите / не можете иметь дескриптор ListView, вы можете найти его, выполнив поиск по визуальному дереву, начиная с только что проверенного элемента управления.Каждое событие «Validated» каждого элемента управления будет обрабатываться обработчиком события «CheckIfAllValidated», и, когда все будет проверено, вы можете вызвать события «AllValidated», которые будут обрабатываться кнопкой (и, возможно, некоторыми другими элементами управления) длявключите его.

Редактировать: Я понял, что вы не хотите, чтобы каждый компонент знал о своих дочерних элементах, но обратите внимание, что даже довольно распространенное событие PropertyChanged имеет поля 'sender', которые сообщают, кто вызвал событие.Таким образом, любой прослушиватель PropertyChanged, скажем, свойства 'validated', может перейти к визуальному дереву, остановиться, когда он встретит ListView, а затем выполнить поиск вниз, если для всех элементов управления, имеющих свойство validated, это свойство установлено в true..

Редактировать 2: Чтобы получить более четкое представление о том, как это сделать, либо в новом окне, либо в событии загрузки окна, либо, возможно, в событии ContentRendered, в зависимости от того, как загружены элементы управления, вы можете использовать один раз.этот код для привязки обработчика ко всем вашим элементам управления:

For Each ThisControl In MainListView. 
   Dim ThisControlType = ThisControl.GetType
   Dim ThisControlPropertyChangedEvent = ThisControlType.GetEvent("PropertyChanged")
   ' you might wanna check here if event is not null / nothing
   ThisControlPropertyChangedEvent.AddEventHandler(ThisControl, New PropertyChangedEventHandler(AddressOf APropChanged))
 Next

и вы пишете APropChanged как-то так:

Public Sub APropChanged(ByVal sender As Object, ByVal e As PropertyChangedEventArgs)
If e.PropertyName = "Validated" Then
    Dim ValidatedForAll = True
    For Each ThisControl In MainListView.Items
        Dim ThisControlType = ThisControl.GetType
        Dim ThisControlValidatedProperty = ThisControlType.GetProperty("Validated")
        'you might wanna check for non null here
        If Not ThisControlValidatedProperty.GetValue(ThisControl, Nothing) Then
           ValidatedForAll = False
           Exit For
        End If
    Next
    If ValidatedForAll Then
       MessageBox.Show("Yeeppee")    ' you might send an event instead.
    End If
End If
End Sub

Редактировать 3: вы можете сделать это еще прощес пользовательским событием "ValidatedChanged ()", которое вы можете подключить таким же образом.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...