Как мне создать UserControl, который связывается "нормально"? - PullRequest
1 голос
/ 07 октября 2011

Я объясню, что я имею в виду.

Допустим, я обернул TextBox в UserControl и выставил свойство Id Чтобы связать это свойство, оно должно быть свойством Dependency.Хорошо, здесь мы идем (обратите внимание на глупый танец с установщиком свойств вызовов OnIdChanged, чтобы мы работали с INotifyPropertyChanged):

public static readonly DependencyProperty IdProperty =
            DependencyProperty.RegisterAttached("Id", typeof(string), typeof(MyTextBox), new PropertyMetadata(OnIdChanged));

public string Id
        {
            get
            {
                return (string)GetValue(IdProperty);
            }

            set
            {
                this.SetValue(IdProperty, value);
                this.OnPropertyChanged("Id");
            }
        }

private static void OnIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            (d as Lookup).Id = e.NewValue as string;
        }

Итак, это все, что мне нужно.Я создаю другой пользовательский элемент управления.Перетащите MyTextBox на него:

    <Lookup:MyTextBox Id="{Binding Source={StaticResource DataContextProxy}, Path=DataSource.CurrentItem.DeviceId, Mode=TwoWay, NotifyOnValidationError=True}"/>

Как видите - мне пришлось использовать DataContextProxy.Честно говоря, это немного магии для меня, я делал это однажды и попробовал сейчас, когда обычный способ не был обязательным.Как мне кодировать свой пользовательский элемент управления, чтобы я мог привязываться к нему следующим образом?

        <Lookup:MyTextBox Id="{Binding Path=CurrentItem.DeviceId, Mode=TwoWay, NotifyOnValidationError=True}"/>

Вот как я могу привязать TextBox рядом с моим пользовательским, и он работает как положено.В чем секрет?

РЕДАКТИРОВАТЬ

Ниже приведены 2 скриншота.Первый показывает, как то, что я получаю в качестве источника при привязке к элементу управления Lookup (настраиваемый UserControl) - указывает на SELF

Второй - следующее поле в моем XAML - это обычное текстовое поле, привязывается к тому же CurrentItem, но имеет источникииз моей ViewModel enter image description here enter image description here

EDIT 2

Я понял, почему DataContext указывает на сам UserControl.Я понял почему , но не понимаю почему ..

В моем коде UserControl (Lookup) после инициализации я установил this.DataContext = this, чтобы внутри элемента управления он связывался с внутренними свойствами.Каким-то образом это распространилось на родительский ViewModel.После того, как я изменил этот код на LayoutRoot.DataContext = this - проблема решена.Но я не понимаю, почему это так, и я все еще не могу получить хорошую маршрутизацию свойств через ..

1 Ответ

2 голосов
/ 07 октября 2011

Я освещал эту проблему в своем блоге, который я написал некоторое время назад .Если вы установите DataContext для UserControl на себя, вы больше не сможете помещать его в другой UserControl или Window и ожидать, что он унаследует DataContext своего родителя.Это означает, что вы не можете просто оставить его в своем представлении и указать привязки к вашей модели представления.Причины этого в том, что вы заблокировали наследование вашего ViewModel DataContext.Любые свойства, предоставляемые вашим UserControl, будут иметь свой источник привязки, установленный на UserControl.

Решение состоит в том, чтобы установить DataContext некоторого элемента в UserControl на сам UserControl.Обычно вы устанавливаете непосредственный дочерний элемент UserControl.

...