Не удается найти источник для привязки со ссылкой во вложенных шаблонах Style / DataGrid DataTemplates - PullRequest
0 голосов
/ 29 января 2020

У меня есть Control (ZlsUnitBrowserActive) с двумя DependencyProperties MaxWidthIdentifier / PropertiesDataTemplate. Я застрял, когда пытаюсь связать эти два свойства в Style:

System. Windows .Data Ошибка: 4: Не удается найти источник для привязки со ссылкой 'RelativeSource FindAncestor, AncestorType = 'PlcFramework.Zls.Production.ProductionControls.ZlsUnitBrowserActive', AncestorLevel = '1' '. BindingExpression: Path = PropertiesDataTemplate; DataItem = NULL; целевым элементом является DataGridTemplateColumn (HashCode = 30225241); Свойство target - CellTemplate (тип DataTemplate)

<Style TargetType="productionControls:ZlsUnitBrowserActive">
    <Style.Setters>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="productionControls:ZlsUnitBrowserActive">
                    <DataGrid>
                        <DataGrid.Columns>
                            <DataGridTemplateColumn>
                                <DataGridTemplateColumn.CellTemplate 
                                    MaxWidth="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=productionControls:ZlsUnitBrowserActive}, Path=MaxWidthIdentifier}"
                                    CellTemplate="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=productionControls:ZlsUnitBrowserActive}, Path=PropertiesDataTemplate}"/>
                            </DataGridTemplateColumn>
                        </DataGrid.Columns>
                    </DataGrid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style.Setters>
</Style>

Есть ли специальный прием? Также попытался кэшировать экземпляр ZlsUnitBrowserActive в DataGrid.Tag (см. Сообщение: { ссылка }), но безуспешно.

Ответы [ 2 ]

1 голос
/ 29 января 2020

Причина, по которой вы не можете связать свойство DataGridColumn с визуальным предком, используя RelativeSource, заключается в том, что сам столбец не является частью визуального дерева, поэтому у него нет предков для привязки.

Элемент управления DataGrid является частью визуального дерева, и «BindingProxy» можно использовать для привязки и «захвата» DataContext, например, используя RelativeSource из DataGrid.

Томас Левеск написал сообщение в блоге, в котором это подробно объясняется: https://thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/.

0 голосов
/ 29 января 2020

Я нашел решение. Хитрость заключается в использовании "BindingProxy".

Я не совсем понял, почему мне пришлось так решать. Может быть, кто-то может дать мне объяснение или опубликовать лучшее решение. 100

public class BindingProxy : Freezable
{
    public static readonly DependencyProperty DataProperty;

    static BindingProxy()
    {
        DataProperty = DependencyProperty.Register(nameof(Data), typeof(object), typeof(BindingProxy));
    }

    public object Data
    {
        get => GetValue(DataProperty);
        set => SetValue(DataProperty, value);
    }

    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }
}
<Style TargetType="productionControls:ZlsUnitBrowserActive">
    <Style.Setters>
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="productionControls:ZlsUnitBrowserActive">
                    <DataGrid>
                        <DataGrid.Resources>
                            <xamlHelper:BindingProxy x:Key="DataContextBindingProxy" Data="{Binding RelativeSource={RelativeSource TemplatedParent}}"/> 
                        </DataGrid.Resources>
                        <DataGrid.Columns>
                            <DataGridTemplateColumn>
                                <DataGridTemplateColumn.CellTemplate 
                                    MaxWidth="{Binding Path=Data.MaxWidthIdentifier, Source={StaticResource DataContextBindingProxy}}"
                                    CellTemplate="{Binding Path=Data.MaxWidthIdentifier, Source={StaticResource PropertiesDataTemplate}"/>
                            </DataGridTemplateColumn>
                        </DataGrid.Columns>
                    </DataGrid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style.Setters>
</Style>
...