Итак, вот вопрос, который заставляет меня бегать кругами. Я работаю со встроенной структурой класса, которая должна сохранять свои дочерние объекты частными, но должна иметь возможность передавать определенные события NotifyOfPropertyChange вверх по лестнице из данных в этих дочерних объектах. Каков наилучший способ сделать это.
Мой текущий подход - код ниже, где мое представление для SystemViewModel (SystemView) имеет элемент, связанный со свойством CommunicationStatus
, и у меня есть родительский класс SystemViewModel, у которого есть дочерний класс CommunicationManager, у которого есть дочерний класс Communicator как
Вещи, которые затрудняют это:
1) В этом случае ДОЛЖНО быть допущено, что Communicator не имеет видимости SystemViewModel, поэтому в методе set
в Communicator следует ввести NotifyOfPropertyChanged(() => CommunicationStatus)
Свойство Connected
не должно быть опцией ... если только я не упустил что-то очевидное.
2) SystemViewModel не должен иметь прямой доступ к коммуникатору, поэтому привязка от SystemView.xaml
к Connected
невозможна быть сделано.
На мой взгляд, событие NotifyOfPropertyChanged в Connected
должно всплыть для родителей из-за реализации PropertyChangedBase
во всех классах, но этого не происходит. Буду рад любой помощи!
public class SystemViewModel : PropertyChangedBase
{
private CommunicationManager CommunicationManager;
public string CommunicationStatus
{
get
{
if (CommunicationManager.YepConnected)
{
return "Green";
}
else
{
return "Red";
}
}
}
}
public class CommunicationManager : PropertyChangedBase
{
private Communicator Communicator;
public bool YepConnected { get { return Communicator.Connected; } }
}
public class Communicator: PropertyChangedBase
{
private bool _connected;
public bool Connected
{
get { return _connected; }
set
{
_connected = value;
NotifyOfPropertyChange(() => Connected);
}
}
}
РЕДАКТИРОВАТЬ
Таким образом, похоже, что это работает правильно и передает событие, как ожидается, от дочернего класса к родительскому классу. Реальная проблема, которая была немного более глубокой, связана с тем, как привязка WPF связана со свойством. Просто для справки, используемый мной XAML выглядит следующим образом:
<TextBlock Text="Status" Background="{Binding CommunicationStatus}"/>
Кроме того, я использовал SolidColorBrush
вместо string
(хотя они оба связаны одинаково и работают).
Проблема в том, что когда событие уведомления распространяется от Connected
до CommunicationStatus
, оно останавливается там и не распространяется на привязку XAML (нигде в моем коде не используется CommunicationStatus
, кроме как в XAML связывание). Я знаю, что привязка работает, потому что при отладке я вижу, что когда программа запускается изначально, цвет устанавливается на красный при выполнении метода CommunicationStatus
get
, предположительно вызываемого из привязки XAML. После запуска кода CommunicationStatus
обновляется каждый раз, когда Connected
, но привязка XAML больше не наблюдает за этим изменением. Если я вручную реализую NotifyOfPropertyChange(() => CommunicationStatus);
, обязательный элемент решает обновить. Однако, поскольку я не использую какой-либо метод set
в CommunicationStatus
(и событие notify не распространяется вверх), кажется, нет простого способа сообщить XAML, что мое значение изменилось.
Схематичное решение: Следите за изменениями CommunicationStatus
и вызовите событие NotifyOfPropertyChange(() => CommunicationStatus);
следующим образом:
public class SystemViewModel : Conductor<object>
{
private CommunicationManager CommunicationManager;
private SolidColorBrush LastCommunicationStatusValue = new SolidColorBrush();
public SolidColorBrush CommunicationStatus
{
get
{
SolidColorBrush CurCommunicationStatusValue;
if (CommunicationManager.YepConnected)
{
CurCommunicationStatusValue = new SolidColorBrush(Colors.Green);
}
else
{
CurCommunicationStatusValue = new SolidColorBrush(Colors.Red);
}
if (CurCommunicationStatusValue.Color != LastCommunicationStatusValue.Color)
{
LastCommunicationStatusValue = CurCommunicationStatusValue;
NotifyOfPropertyChange(() => CommunicationStatus);
}
return CurCommunicationStatusValue;
}
}
}
И да, если вы не сделаете это идеально, это мгновенное переполнение стека (каламбур). Всякий раз, когда изменяется значение Connected
, я наблюдаю, как выполняется метод CommunicationStatus
get
. Таким образом, это выполнение приводит к другому выполнению метода get
, только на этот раз обновления XAML.
Может кто-нибудь объяснить, почему это решение работает, и / или предложить более красноречивое решение?