Установка пользовательских свойств в UserControl через DataBinding - PullRequest
14 голосов
/ 10 мая 2009

Скажем, у меня есть очень простой UserControl, который - для всех намерений и целей - не более чем TextBox:

public partial class FooBox : UserControl
{
    public static readonly DependencyProperty FooTextProperty =
        DependencyProperty.Register("FooText", typeof(string), typeof(FooBox));

    public FooBox()
    {
        InitializeComponent();
    }

    public string FooText
    {
        get { return textBlock.Text; }
        set { textBlock.Text = value; }
    }
}

<UserControl x:Class="Namespace.FooBox"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <Grid>
        <TextBlock x:Name="textBlock" />
    </Grid>
</UserControl>

В форме он объявлен как:

<local:FooBox FooText="{Binding Name}" />

DataContext формы устанавливается для объекта, который имеет свойство Name. Но это не работает для меня. Чего мне не хватает?

Ответы [ 2 ]

19 голосов
/ 11 мая 2009

Части "get" и "set" объявления свойства в DependencyProperty на самом деле не вызываются системой привязки данных WPF - они там, по сути, для удовлетворения только компилятора.

Вместо этого измените объявление свойства, чтобы оно выглядело так:

public string FooText
{
    get { return (string)GetValue(FooTextProperty); }
    set { SetValue(FooTextProperty, value); }
}

... и ваш XAML:

<UserControl ...
    x:Name="me">
    <Grid>
        <TextBlock Text="{Binding FooText,ElementName=me}" />
    </Grid>
</UserControl>

Теперь ваш TextBox.Text просто привязывается непосредственно к свойству «FooText», поэтому вы можете в свою очередь привязать свойство FooText к «Name», как вы это делаете в настоящее время.

Другим способом является привязка TextBlock.Text к привязке RelativeSource, которая находит свойство FooText первого предка типа «FooBox», но я обнаружил, что это более сложно, чем просто дать элементу управления внутреннее x: Name и используя привязку элемента.

6 голосов
/ 11 мая 2009

Оказывается, настоящая проблема в том, что я ожидал, что инфраструктура WPF установит мое открытое свойство, после чего мой код будет реагировать на изменения и отображать их в соответствии с новым значением. Не так. WPF напрямую вызывает SetValue () и полностью обходит открытое свойство. Что мне нужно было сделать, это получить уведомления об изменении свойства с помощью DependencyPropertyDescriptor.AddValueChanged и ответить на это. Это выглядит примерно так (внутри ctor):

var dpd = DependencyPropertyDescriptor
    .FromProperty(MyDependencyProperty, typeof(MyClass));
dpd.AddValueChanged(this, (sender, args) =>
{
    // Do my updating.
});
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...