Привязка данных к UserControl в WPF - PullRequest
11 голосов
/ 16 июля 2010

У меня есть UserControl, который я хочу участвовать в привязке данных.Я установил свойства зависимостей в пользовательском элементе управления, но не могу заставить его работать.

UC отображает правильный текст, когда я вызываю его статическим текстом (например, BlueText = "ABC").Когда я пытаюсь привязать его к локальному общедоступному свойству, оно всегда пустое.

<src:BlueTextBox BlueText="Feeling blue" />            <!--OK-->
<src:BlueTextBox BlueText="{Binding Path=MyString}" /> <!--UserControl always BLANK!-->
<TextBox Text="{Binding Path=MyString}" Width="100"/>  <!--Simple TextBox Binds OK-->

Я свел код к следующему упрощенному примеру.Вот XAML UserControl:

    <UserControl x:Class="Binding2.BlueTextBox" ...
    <Grid>
        <TextBox x:Name="myTextBox" Text="{Binding BlueText}" Foreground="Blue" Width="100" Height="26" />
    </Grid>

Вот код позади UserControl:

public partial class BlueTextBox : UserControl
{
    public BlueTextBox()
    {
        InitializeComponent(); 
        DataContext = this; // shouldn't do this - see solution
    }

    public static readonly DependencyProperty BlueTextProperty =
        DependencyProperty.Register("BlueText", typeof(string), typeof(BlueTextBox));

    public string BlueText
    {
        get { return GetValue(BlueTextProperty).ToString(); }
        set { SetValue( BlueTextProperty, value.ToString() ); }
    }

Кажется, это должно быть действительно легко, но я не могу сделатьэто работает.Спасибо за вашу помощь!

Дополнительная информация: Когда я пробовал исправление, предложенное Юджином, я заметил некоторое странное поведение.Я добавил PropertyChangedCallback к метаданным;это позволяет мне наблюдать за значением BlueText.При установке строки в статическое значение (= «синий») событие PropertyChanged срабатывает.В случае привязки данных не запускается PropertyChanged.Я думаю, это означает, что привязанное к данным значение не отправляется в UserControl.(Я думаю, что конструктор не вызывается в статическом случае)

Решение: Проблемы были правильно определены Arcturus и jpsstavares.Сначала я переписывал привязку данных, когда в конструкторе элемента управления установлено значение DataContext = this.Это предотвратило получение значения привязки данных.Мне также пришлось назвать элемент управления x: Name = root и указать Binding ElementName = root в XAML.Чтобы получить привязку TwoWay, мне нужно было установить Mode = TwoWay в вызывающей стороне.Вот правильный код:

<src:BlueTextBox BlueText="{Binding Path=MyString, Mode=TwoWay}}" /> <!--OK-->

Теперь XAML в UserControl:

    <UserControl x:Class="Binding2.BlueTextBox" x:Name="root"...
    <Grid>
        <TextBox x:Name="myTextBox" Text="{Binding ElementName=root, Path=BlueText}" Foreground="Blue" Width="100" Height="26" />
    </Grid>

Наконец я удалил DataContext = this в конструкторе UserControl.

    public BlueTextBox()
    {
        InitializeComponent(); 
        //DataContext = this; -- don't do this
    }

Спасибо всем за огромную помощь!

Ответы [ 4 ]

12 голосов
/ 16 июля 2010

Вы устанавливаете DataContext в элементе управления на себя, тем самым перезаписывая DataContext при использовании этого элемента управления в других элементах управления.Возьмем для примера привязку в вашей ситуации:

<src:BlueTextBox BlueText="{Binding Path=MyString}" /> 

После загрузки и установки всего Datacontext он будет искать путь MyString в вашем элементе управления BlueTextBox, поскольку вы устанавливаете для него DataContext.Я предполагаю, что это не то, как вы хотели, чтобы это работало;).

Решение:

Измените текстовую привязку либо на одну из двух привязок:

{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type src:BlueTextBox}}, Path=BlueText}

или

Назовите свой корневой элемент управления (или что-то в этом роде)

<UserControl x:Name="Root"

{Binding ElementName=Root, Path=BlueText}

И удалите

DataContext = this;

из конструктора вашего UserControl, и он должен работать как шарм..

2 голосов
/ 16 июля 2010

Я думаю, что в этом случае вам нужно установить свойство ElementName в привязке. Как то так:

<UserControl x:Class="Binding2.BlueTextBox" x:Name="blueTextBox"...
<Grid>
    <TextBox x:Name="myTextBox" Text="{Binding ElementName=blueTextBox, Path=BlueText}" Foreground="Blue" Width="100" Height="26" />
</Grid>
0 голосов
/ 04 июля 2011

Я знаю, что это старая тема, но все же.

Также укажите PropertyChangedCallback на UIPropertyMetadata во время регистрации DP

0 голосов
/ 16 июля 2010

Возможно, вам нужно добавить в ваше свойство FrameworkPropertyMetadata, где укажите FrameworkPropertyMetadataOptions.AffectsRender и AffectsMeasure.

Перечисление FrameworkPropertyMetadataOptions MSDN, статья

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...