WPF, предоставляющий вычисляемое свойство для привязки (как DependencyProperty)
У меня есть сложный контроль WPF, который по некоторым причинам (т. е. performance) использует не свойства зависимостей, а простые свойства C# (по крайней мере, на верхнем уровне они представлены как свойства).
Цель состоит в том, чтобы сделать возможным привязку к некоторым из этих свойств верхнего уровня -> я думаю, что я должен объявить их как DPs.(верно? или есть какой-то другой способ достичь этого? )
Я начал читать на MSDN о DependencyProperties и DependencyObjects и нашел Пример:
public class MyStateControl : ButtonBase
{
public MyStateControl() : base() { }
public Boolean State
{
get { return (Boolean)this.GetValue(StateProperty); }
set { this.SetValue(StateProperty, value); }
}
public static readonly DependencyProperty StateProperty = DependencyProperty.Register(
"State", typeof(Boolean), typeof(MyStateControl),new PropertyMetadata(false));
}
Если я прав - этот код принуждает свойство быть поддержанным DependencyProperty, который ограничивает его, чтобы быть простым свойством с хранилищем (с функциональной точки зрения, не технически) вместо того, чтобы вычислять значение свойства каждый раз, когда вызывается getter и устанавливать другие свойства/поля каждый раз, когда вызывается setter.
Что я могу с этим поделать? Есть ли какой-нибудь способ заставить эти два мира встретиться в какой-то момент?
/ / править
Думаю, что да. чтобы рассказать вам немного больше о том, что я хочу делать и каковы мои ограничения. Итак:
У меня есть TabControl, который привязан к коллекции объектов ViewModel (я использую шаблон MVVM). Каждая вкладка предназначена для редактирования одного объекта этой коллекции. Объекты могут быть разных типов, поэтому у меня есть несколько определений, каждое из которых имеет свое свойство типа данных. Теперь у меня есть этот сложный элемент управления WPF, который я хочу использовать как часть одной из этих таблиц DataTemplates. Если я использую обычное текстовое поле, я могу просто привязка к свойству Text, но я не могу сделать то же самое со свойством Text этого пользовательского элемента управления просто потому, что его свойство Text не является свойством зависимостей.
В этом сценарии у меня есть:
- нет прямого доступа ни к самому элементу управления, ни к его событиям
- нет кода за файлом, который я мог бы использовать для таких вещей
Я вижу, однако, грязное решение -
- в классе Window я должен был бы подписаться на событие CollectionChanged коллекции это связано с TabControl.
- всякий раз, когда элемент добавляется в эту коллекцию, используйте ItemContainerGenerator для получения копии I suppose TabItem и используйте его для поиска правильной копии "сложного элемента управления"
- Regiter items обработчики событий 'complex controls' для выполнения задания
Это неверно, потому что:
- это agains MVVM - я должен играть с tab control, чтобы сделать работу, а не делать это в классе ViewModel
- это пары в нежелательном способ просмотра и viewmodel
2 ответов:
Мне кажется, что вы были обременены пользовательским элементом управления WPF, который был построен кем-то, кто не намеревался использовать его с привязкой данных. Я бы предположил, что это происходит по одной из двух причин: а) есть какая-то логическая причина, по которой вы не должны быть в состоянии привязать к этому свойству, или б) первоначальный автор этого элемента управления не знал, что он делает. Вы не предоставили мне достаточно информации, чтобы понять, над каким из этих двух условий вы действительно работаете. под.
Но в целом причина, по которой вы не можете предоставить вычисляемые свойства для привязки, заключается в том, что вычисляемые свойства обычно не имеют сеттера. Не имеет смысла устанавливать свойство, значение которого вычисляется.
Если существуют другие свойства, значения которых должны обновляться при изменении этого свойства, правильный подход (или, по крайней мере, тот, который согласуется с дизайном свойств зависимостей) заключается в обработке этих обновлений в функции обратного вызова свойства зависимостей, которая является вроде того, для чего предназначена функция обратного вызова.
Я думаю, что Вы путаете свойства зависимостей и реализуете
INotifyPropertyChangedна своих классах.Вам не нужно, чтобы ваше свойство было свойством зависимости, вам просто нужно, чтобы ваш класс реализовывал
Итак, предположим, что у вас есть свойствоINotifyPropertyChangedи вызывалOnPropertyChangedвсякий раз, когда состояние вашего объекта изменяется таким образом, что это повлияло бы на значение, которое вы хотите предоставить привязке.Sum, к которому вы хотите привязаться. СВОЙСТВОSumsimple добавляет два других свойства (или поля, или что угодно) вместе. Когда что-либо происходит, что влияет на вычислениеSum, вы хотите уведомить, что значениеSumизменилось, поэтому любые элементы управления, связанные сSum, обновляются.public int Sum => Value1 + Value2; public int Value1 { set { // changing this affects "Sum", so I need to notify that the binding should update _value1 = value; OnPropertyChanged("Sum"); } } public int Value2 { set { // changing this affects "Sum", so I need to notify that the binding should update _value2 = value; OnPropertyChanged("Sum"); } }
Comments