Я хочу написать ViewModel, который всегда знает текущее состояние некоторых свойств зависимостей только для чтения из View.
В частности, мой графический интерфейс содержит FlowDocumentPageViewer, который отображает по одной странице из FlowDocument. FlowDocumentPageViewer предоставляет два свойства зависимостей, доступных только для чтения, которые называются CanGoToPreviousPage и CanGoToNextPage. Я хочу, чтобы моя ViewModel всегда знала значения этих двух свойств View.
Я подумал, что могу сделать это с привязкой данных OneWayToSource:
<FlowDocumentPageViewer
CanGoToNextPage="{Binding NextPageAvailable, Mode=OneWayToSource}" ...>
Если бы это было разрешено, это было бы идеально: всякий раз, когда свойство CanGoToNextPage в FlowDocumentPageViewer изменялось, новое значение передавалось в свойство NextPageAvailable ViewModel, а это именно то, что я хочу.
К сожалению, это не компилируется: я получаю сообщение об ошибке, что свойство CanGoToPreviousPage доступно только для чтения и не может быть установлено из разметки. Очевидно, свойства, доступные только для чтения, не поддерживают никакую привязку данных, даже привязку данных, доступную только для чтения в отношении этого свойства.
Я мог бы сделать свои свойства ViewModel DependencyProperties и сделать привязку OneWay в другую сторону, но я не в восторге от нарушения разделения проблем (ViewModel потребуется ссылка на View, которого привязка данных MVVM должна избегать ).
FlowDocumentPageViewer не предоставляет событие CanGoToNextPageChanged, и я не знаю ни одного хорошего способа получать уведомления об изменениях из DependencyProperty, кроме создания другого DependencyProperty для его привязки, что здесь кажется излишним.
Как я могу информировать мою модель представления об изменениях свойств представления, доступных только для чтения?
источник
Size
свойство, сочетая высоту и ширину. Прибл. На 50% меньше кода.ActualSize
собственностиFrameworkElement
. Если вы хотите напрямую привязать прикрепленные свойства, вы должны создать два свойства, которые будут привязаны кActualWidth
и,ActualHeight
соответственно.Я использую универсальное решение, которое работает не только с ActualWidth и ActualHeight, но и с любыми данными, к которым вы можете привязаться хотя бы в режиме чтения.
Разметка выглядит так, если ViewportWidth и ViewportHeight являются свойствами модели представления.
Вот исходный код для настраиваемых элементов
источник
Target
свойство необходимо сделать доступным для записи, хотя его нельзя изменять извне: - /Если кому-то еще интересно, я закодировал здесь приближение решения Кента:
Не стесняйтесь использовать его в своих приложениях. Это работает хорошо. (Спасибо, Кент!)
источник
Вот еще одно решение этой «ошибки», о которой я писал здесь:
Привязка OneWayToSource для свойства зависимости ReadOnly
Он работает с использованием двух свойств зависимостей, прослушивателя и зеркала. Слушатель привязан OneWay к TargetProperty, а в PropertyChangedCallback он обновляет свойство Mirror, которое привязано OneWayToSource к тому, что было указано в привязке. Я называю его,
PushBinding
и его можно установить для любого свойства зависимостей только для чтения, например этогоЗагрузите демонстрационный проект здесь .
Он содержит исходный код и краткий пример использования, или посетите мой блог WPF, если вас интересуют детали реализации.
И последнее замечание: начиная с .NET 4.0 мы еще дальше отошли от встроенной поддержки для этого, поскольку привязка OneWayToSource считывает значение обратно из источника после его обновления.
источник
Мне нравится решение Дмитрия Ташкинова! Однако он разбил мой VS в режиме проектирования. Поэтому я добавил в метод OnSourceChanged строку:
источник
Я думаю, что это можно сделать немного проще:
XAML:
CS:
источник