Привязка внутри DataTemplate к самому себе

279
18 февраля 2017, 04:31

Есть базовый класс Action обозначающий действие:

public class BaseAction
{
    public string Name  {get;set;}
}

И есть класс-наследник ExpanderAction, который обозначает череду таких действий:

public class ExpanderAction : BaseAction
{
    public List<BaseAction> Actions {get;set;} = new List<BaseAction>();
}

Также существует коллекция элементов, которая привязана к ItemsControl:

public ObservableCollection<BaseAction> Actions {get;set;} = new ObservableCollection<BaseAction>();

Элементы коллекции могут быть представлены 2 видами: кнопкой или другой коллекцией с элементами. Нужный шаблон выбирается через ItemTemplateSelector.

<DataTemplate x:Key="BaseActionTemplate"  DataType="{x:Type actions:BaseAction}">
    <Button Content="{Binding Name}" />
</DataTemplate>
<DataTemplate x:Key="ExpanderActionTemplate" DataType="{x:Type actions:ExpanderAction}">
    <ItemsControl ItemsSource="{Binding Actions}" />
</DataTemplate>

Проблема в том, что внутри ItemsControl, который лежит в шаблоне ExpanderActionTemplate элементы нужно отобразить также 2-я теми же самыми шаблонами. Получается что-то вроде рекурсии.

Подскажите, как указать внутри ExpanderActionTemplate, что данные в ItemsControl должны отображаться его же шаблоном?

Update

Делаю так, но возникает ошибка на строке Second="{StaticResource Second}". Это происходит из-за того, что селектор объявлен раньше, чем шаблон данных Second.

<Window.Resources>
    <DataTemplate x:Key="First">
        <Button Content="{Binding Name}" />
    </DataTemplate>
    <local:Selector x:Key="Selector"
                    First="{StaticResource First}" 
                    Second="{StaticResource Second}"/>
    <DataTemplate  x:Key="Second">
        <ItemsControl ItemTemplateSelector="{StaticResource Selector}" 
                      ItemsSource="{Binding Path=ChildActions}"/>
    </DataTemplate>
</Window.Resources>
<StackPanel>
    <ItemsControl ItemsSource="{Binding Actions}" 
    ItemTemplateSelector="{StaticResource Selector}"  />
</StackPanel>
Answer 1

У меня компилируется так:

<Window.Resources>
    <DataTemplate x:Key="First">
        <Button Content="{Binding Name}" />
    </DataTemplate>
    <DataTemplate x:Key="Second">
        <ItemsControl ItemTemplateSelector="{DynamicResource Selector}" 
                      ItemsSource="{Binding Path=ChildActions}"/>
    </DataTemplate>
    <local:Selector x:Key="Selector"
                First="{StaticResource First}" 
                Second="{StaticResource Second}"/>
</Window.Resources>

(хотя и с предупреждением).

Если вы не хотите использовать DynamicResource, можно обойтись и без него за счёт code-behind:

<Window.Resources>
    <local:Selector x:Key="Selector"/>
    <DataTemplate x:Key="First">
        <Button Content="{Binding Name}" />
    </DataTemplate>
    <DataTemplate x:Key="Second">
        <ItemsControl ItemTemplateSelector="{StaticResource Selector}" 
                      ItemsSource="{Binding Path=ChildActions}"/>
    </DataTemplate>
</Window.Resources>
public MainWindow()
{
    InitializeComponent();
    // обязательно после InitializeComponent
    var selector = (Selector)Resources["Selector"];
    selector.First = (DataTemplate)Resources["First"];
    selector.Second = (DataTemplate)Resources["Second"];
}
Answer 2

Можно найти родительский ItemsControl и забрать у него свойство ItemTemplateSelector:

<DataTemplate x:Key="ExpanderActionTemplate" DataType="{x:Type actions:ExpanderAction}">
    <ItemsControl ItemsSource="{Binding Actions}" 
                  ItemTemplateSelector="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}, Path=ItemTemplateSelector}"/>
</DataTemplate>
READ ALSO
Вернуть переменную ref из метода

Вернуть переменную ref из метода

В классе Func есть метод:

576
Ошибка десериализации простейшего json

Ошибка десериализации простейшего json

Есть jsonПытаюсь через Newtonsoftjson привести его к классу

381
Как добавить scintilla в visual studio

Как добавить scintilla в visual studio

Люди добрые, помогите установить компонент scintilla visual studio 2010Компонент добавляется, но при добавлении в форму выдает ошибку

332