Ответ 1
Недавно я рассказал об этой точной проблеме. Я включаю атрибут [DependsUpon("Size")]
с Rectangle. Я ДЕЙСТВИТЕЛЬНО люблю этот подход, потому что он сохраняет знания зависимостей с кодом, который создает зависимость, а не наоборот.
Скажем, в каком-то абстрактном базовом классе ViewModel у меня есть свойство plain-old следующим образом:
public Size Size
{
get { return _size; }
set
{
_size = value;
OnPropertyChanged("Size");
}
}
Затем я создаю более конкретный ViewModel, наследующий от предыдущего, который содержит следующее свойство:
public Rect Rectangle
{
get { return new Rect(0, 0, _size.Width, _size.Height); }
}
Теперь, в некоторых классах View я привязываюсь к вышеупомянутому свойству ViewModel Rectangle
. Все работает нормально, пока я не изменю размер. Когда Size
изменяется, Rectangle
не знает об этом, и изменение не распространяется на представление. А так как Rectangle
находится в дочернем классе, я не могу просто добавить OnPropertyChanged("Rectangle")
в установщик Size
.
Теперь представьте, что у меня много разных свойств, таких как Rectangle
, что все зависит от свойств базового класса и что ни одно из этих изменений не распространяется. Мне нужен легкий и элегантный способ связывания уведомлений об изменениях, желательно тот, который не требует большого количества кода и не заставляет меня использовать свойства зависимостей.
Очевидно, здесь много уродливых решений - то, что я ищу, - это что-то чистое и умное. Мне кажется, что это будет очень распространенный сценарий, и мне кажется, что это может быть способ, совместимый с MVVM.
Недавно я рассказал об этой точной проблеме. Я включаю атрибут [DependsUpon("Size")]
с Rectangle. Я ДЕЙСТВИТЕЛЬНО люблю этот подход, потому что он сохраняет знания зависимостей с кодом, который создает зависимость, а не наоборот.
Я использую Josh Smith PropertyObserver, который вы можете получить из его библиотеки Foundation MVVM в http://mvvmfoundation.codeplex.com/.
Использование:
_viewmodel_observer = new PropertyObserver<OtherViewModel>(_OtherViewModel)
.RegisterHandler(m => m.Size, m => RaisePropertyChanged(Rectangle);
Атрибут атрибута Брайана тоже хорош. Одна вещь, которая мне нравится в PropertyObserver, заключается в том, что я могу выполнить произвольный код; позволяя мне проверить условия, которые могут заставить меня избежать рейза или выполнять другие действия вместе.
Вы можете просто переопределить OnPropertyChanged в производном ViewModel, например:
protected override void OnPropertyChanged(string propertyName) {
base.OnPropertyChanged(propertyName);
if (propertyName == "Size") {
base.OnPropertyChanged("Rectangle");
}
}
Другая возможность... Некоторое время назад я собрал довольно красивый базовый класс ViewModel, который поддерживает атрибуты свойств:
[DependsOn("Size")]
public Rect Rectangle {
get { new Rect(0,0,Size.Width, Size.Height); }
}
Затем базовый класс ViewModel собирает эти атрибуты DependOnAttribute во время выполнения и в методе OnPropertyChanged, он в основном просто ищет, какие другие свойства должны быть аннулированы при изменении свойства.
Чистым способом MVVM было бы использовать механизм Messenger (например, в Josh Smith MvvmFoundation)
Создайте объект Singleton Messenger где-то - основной класс приложения всегда является хорошим местом для этого
public partial class App : Application
{
private static Messenger _messenger;
public static Messenger Messenger
{
get
{
if (_messenger == null)
{
_messenger = new Messenger();
}
return _messenger;
}
}
}
В Настройщике размера из базового класса уведомите изменения:
public Size Size
{
get { return _size; }
set
{
_size = value;
OnPropertyChanged("Size");
App.Messenger.NotifyColleagues("SIZE_CHANGED");
}
}
Теперь вы можете позволить вашему унаследованному ViewModel прослушивать эти изменения и, соответственно, поднять события PropertyChanged...
public MyViewModel : MyViewModelBase
{
public MyViewModel()
{
App.Messenger.Register("SIZE_CHANGED", () => OnPropertyChanged("Rectangle"));
}
}
Конечно - вы можете добавить столько подписчиков на это сообщение, сколько вам нужно - по одному для каждого свойства, которое нуждается в изменениях, чтобы получать уведомление в представлении...
Надеюсь, что это поможет:)
возможно, потому что im vB guy, но в вашем коде Rectangle похоже, что вы получаете доступ к приватной декларации _size вместо свойства Public Size, которая не запускает событие OnPropertyChanged для предупреждения о представлении.
Также я могу быть вне базы, но не должен Rectangle быть фактическим объектом, а Size является свойством этого объекта? Возможно, это то, что вы делаете. Некоторые методологии С# по-прежнему очень чужды мне.