Привязки к дочернему объекту зависимости usercontrol не работают - PullRequest
4 голосов
/ 10 февраля 2011

Я пытаюсь получить привязку для работы над дочерним объектом пользовательского элемента управления. Xaml выглядит так:

<MyGrid>
    <MyColumn ExtendedColumnData="{Binding ColumnToolTipDescriptions}"/>
</MyGrid>

Вот как определяются классы:

[ContentProperty("Columns")]
public class MyGrid : UserControl
{
    private MyColumnCollection _columns;

    [DesignerSerializationVisibility(DesignerSerializationVisibility.Content), Category("Data")]
    public MyColumnCollection Columns
    {
        get
        {
            if (_columns == null)
                _columns = new MyColumnCollection();

            return _columns;
        }
    }
}

public class MyColumnCollection : ObservableCollection<MyGridColumn>
{
}

public class MyGridColumn : DependencyObject
{
    public object ExtendedColumnData
    {
        get { return (object)GetValue(ExtendedColumnDataProperty); }
        set { SetValue(ExtendedColumnDataProperty, value); }
    }

    public static readonly DependencyProperty ExtendedColumnDataProperty =
        DependencyProperty.Register("ExtendedColumnData", typeof(object), typeof(MyGridColumn), new UIPropertyMetadata(null));
}

Из того, что я могу сказать, привязка даже не пытается получить данные, так как я пытался сопоставить преобразователь с привязкой, и точка останова в методе Convert никогда не получает удар.

Я использую шаблон MVVM, поэтому свойство DataContext окна установлено на модель представления.

Я прочитал некоторые другие вопросы здесь и попробовал различные перестановки связывания, такие как:

<MyColumn ExtendedColumnData="{Binding DataContext.ColumnToolTipDescriptions, ElementName=MyViewName}" />
<MyColumn ExtendedColumnData="{Binding DataContext.ColumnToolTipDescriptions, RelativeSource={RelativeSource AncestorType={x:Type local:MyView}}" />

Но все равно не повезло, переплет не срабатывает! Раздражает то, что это работает нормально (если я добавлю свойство в сетку):

<MyGrid ExtendedColumnData="{Binding ColumnToolTipDescriptions}">
    <MyColumn />
</MyGrid>

У меня нет опыта работы с WPF, поэтому я уверен, что что-то упустил?

Ответы [ 2 ]

2 голосов
/ 10 февраля 2011

Проблема в том, что MyColumnCollection не наследует контекст данных (обычные свойства элемента управления не являются частью контекста наследования).Если у вас нет контекста данных, привязки работать не будут.

Чтобы исправить это, попробуйте наследовать MyColumnCollection не от ObservableCollection, а от FreezableCollection (свойства freezable являются частью контекста наследования).

0 голосов
/ 02 мая 2018

Проблема в логическом дереве. Прямое решение должно быть (адаптировано к вашему примеру):

public MyColumnCollection Columns
{
    get
    {
        if (_columns == null)
        {
            _columns = new MyColumnCollection();
            _columns.CollectionChanged += Columns_CollectionChanged;
        }
        return _columns;
    }
}

private void Columns_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
    if (e.NewItems != null)
    {
        foreach (var item in e.NewItems)
        {
            AddLogicalChild(item);
        }
    }
    if (e.OldItems != null)
    {
        foreach (var item in e.OldItems)
        {
            RemoveLogicalChild(item);
        }
    }
    // not sure about Action == reset
}

protected override IEnumerator LogicalChildren
{
    get
    {
        return _columns == null ? null : _columns.GetEnumerator();
    }
}

для поддержки логического дерева элементов управления, чтобы dataContext передавался дочерним элементам. Когда вы вызываете AddLogicalChild , он помечает MyGrid как содержащий логические дочерние элементы, тогда LogicalChildren будет прочитано, и будет установлен dataContext этих дочерних элементов (вы можете прослушивать в них событие DataContextChanged). Переопределение LogicalChildren необходимо, поскольку FrameworkElement не хранит список дочерних элементов посредством вызовов AddLogicalChild и RemoveLogicalChild , как ни странно.

...