递归数据模板可能吗?

发布于 2024-09-10 15:27:03 字数 3073 浏览 2 评论 0原文

我有一个类似这样的类:

public class Section
{
    private IEnumerable<Section> sections;
    private IEnumerable<KeyValuePair<string, string>> attributes

    public string Name {get;set;}
    public IEnumerable<Section> Sections
    {
        get {return sections;}
    }
    public IEnumerable<KeyValuePair<string, string>> Attributes
    {
        get {return attributes;}
    }

    public Section(...)
    {
        //constructor logic
    }
}

它包含在另一个类中,为了便于论证,我们将其称为 OtherClass,该类环绕它并在 WPF 中的 ObjectDataProvider 中使用。

正如您所看到的,Section 的一个实例可以包含 Section 的许多其他实例。

XAML 中有没有办法创建处理此递归的模板?

这是我到目前为止所得到的:

<UserControl x:Class="OtherClassEditor"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:OtherClassNS="clr-namespace:NameSpace"
    Height="300" Width="300">
    <UserControl.Resources>
        <ObjectDataProvider ObjectType="{x:Type OtherClassNS:OtherClass}" x:Key="ViewModel" />
        <DataTemplate x:Key="listViewAttr">
            <WrapPanel>
                <TextBlock Text="{Binding Path=Key}"></TextBlock><TextBlock Margin="0,0,4,0">: </TextBlock>
                <TextBlock Text="{Binding Path=Value}"></TextBlock>
            </WrapPanel>
        </DataTemplate>
        <DataTemplate x:Key="listViewSection">
            <StackPanel>
                <WrapPanel Margin="0,0,0,8">
                    <TextBlock Margin="0,0,4,0">Section:</TextBlock>
                    <TextBlock Text="{Binding Path=Name}"/>
                </WrapPanel>
            </StackPanel>
        </DataTemplate>
        <DataTemplate x:Key="listViewData">
            <StackPanel>
                <WrapPanel Margin="0,0,0,8">
                    <TextBlock Margin="0,0,4,0">Section: </TextBlock>
                    <TextBlock Text="{Binding Path=Name}"/>
                    <ListView DataContext="{Binding Path=Sections}" ItemTemplate="{StaticResource listViewSection}" ItemsSource="{Binding Sections}">
                    </ListView>
                    <ListView DataContext="{Binding Path=Attributes}" ItemsSource="{Binding Attributes}" ItemTemplate="{StaticResource listViewAttr}">

                    </ListView>
                </WrapPanel>
            </StackPanel>    
        </DataTemplate>
    </UserControl.Resources>
    <Grid>
        <ListView DataContext="{StaticResource ViewModel}" ItemTemplate="{StaticResource listViewData}" ItemsSource="{Binding Sections}">
        </ListView>
    </Grid>
</UserControl>

但我无法获得递归,因为 DataTemplate 只能引用在它之前声明的一个。

这可以在 XAML 中完成吗?如果是这样,怎么办?这是我必须在代码后面做的事情吗?

DataTemplates 是正确的选择吗?有没有更好的方法来显示和编辑这些数据?

I have a class something like:

public class Section
{
    private IEnumerable<Section> sections;
    private IEnumerable<KeyValuePair<string, string>> attributes

    public string Name {get;set;}
    public IEnumerable<Section> Sections
    {
        get {return sections;}
    }
    public IEnumerable<KeyValuePair<string, string>> Attributes
    {
        get {return attributes;}
    }

    public Section(...)
    {
        //constructor logic
    }
}

Which is contained in another class, lets call it OtherClass for sake of argument, that wraps around it and is used in WPF in an ObjectDataProvider.

As you can see, an instance of Section can contain many other instances of Section.

Is there a way in XAML to create a template that deals with this recursion?

This is what I've got so far:

<UserControl x:Class="OtherClassEditor"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:OtherClassNS="clr-namespace:NameSpace"
    Height="300" Width="300">
    <UserControl.Resources>
        <ObjectDataProvider ObjectType="{x:Type OtherClassNS:OtherClass}" x:Key="ViewModel" />
        <DataTemplate x:Key="listViewAttr">
            <WrapPanel>
                <TextBlock Text="{Binding Path=Key}"></TextBlock><TextBlock Margin="0,0,4,0">: </TextBlock>
                <TextBlock Text="{Binding Path=Value}"></TextBlock>
            </WrapPanel>
        </DataTemplate>
        <DataTemplate x:Key="listViewSection">
            <StackPanel>
                <WrapPanel Margin="0,0,0,8">
                    <TextBlock Margin="0,0,4,0">Section:</TextBlock>
                    <TextBlock Text="{Binding Path=Name}"/>
                </WrapPanel>
            </StackPanel>
        </DataTemplate>
        <DataTemplate x:Key="listViewData">
            <StackPanel>
                <WrapPanel Margin="0,0,0,8">
                    <TextBlock Margin="0,0,4,0">Section: </TextBlock>
                    <TextBlock Text="{Binding Path=Name}"/>
                    <ListView DataContext="{Binding Path=Sections}" ItemTemplate="{StaticResource listViewSection}" ItemsSource="{Binding Sections}">
                    </ListView>
                    <ListView DataContext="{Binding Path=Attributes}" ItemsSource="{Binding Attributes}" ItemTemplate="{StaticResource listViewAttr}">

                    </ListView>
                </WrapPanel>
            </StackPanel>    
        </DataTemplate>
    </UserControl.Resources>
    <Grid>
        <ListView DataContext="{StaticResource ViewModel}" ItemTemplate="{StaticResource listViewData}" ItemsSource="{Binding Sections}">
        </ListView>
    </Grid>
</UserControl>

But I can't get recursion, as a DataTemplate can only reference one that is declared before it.

Can this be done in XAML? If so, how? Is this something that I'll have to do in code behind?

Are DataTemplates even the way to go? Is there a better way to display and edit this data?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

我最亲爱的 2024-09-17 15:27:03

如果有人需要了解如何在不使用 HierarchicalDataTemplate 的情况下执行此操作:

<UserControl x:Class="OtherClassEditor"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:OtherClassNS="clr-namespace:NameSpace"
    Height="300" Width="300">
    <UserControl.Resources>
        <ObjectDataProvider ObjectType="{x:Type OtherClassNS:OtherClass}" x:Key="ViewModel" />
        <DataTemplate x:Key="listViewAttr">
            <WrapPanel>
                <TextBlock Text="{Binding Path=Key}"></TextBlock>
                <TextBlock Margin="0,0,4,0">: </TextBlock>
                <TextBlock Text="{Binding Path=Value}"></TextBlock>
            </WrapPanel>
        </DataTemplate>
        <DataTemplate x:Key="listViewData">
            <StackPanel>
                <WrapPanel Margin="0,0,0,8">
                    <TextBlock Margin="0,0,4,0">Section: </TextBlock>
                    <TextBlock Text="{Binding Path=Name}"/>
                </WrapPanel>
                <ListView ItemTemplate="{DynamicResource listViewData}" ItemsSource="{Binding Sections}" />
                <ListView ItemsSource="{Binding Attributes}" ItemTemplate="{StaticResource listViewAttr}" />
            </StackPanel>    
        </DataTemplate>
    </UserControl.Resources>
    <Grid>
        <ListView DataContext="{StaticResource ViewModel}" ItemTemplate="{DynamicResource listViewData}" ItemsSource="{Binding Sections}">
        </ListView>
    </Grid>
</UserControl>

这基本上可以满足我的需求。

主要更改如 Dan Bryant 建议的那样:更改 ItemTemplate 为递归对象 (Section) 使用动态资源而不是静态资源。

In case anyone needs to see how to do this without using an HierarchicalDataTemplate:

<UserControl x:Class="OtherClassEditor"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:OtherClassNS="clr-namespace:NameSpace"
    Height="300" Width="300">
    <UserControl.Resources>
        <ObjectDataProvider ObjectType="{x:Type OtherClassNS:OtherClass}" x:Key="ViewModel" />
        <DataTemplate x:Key="listViewAttr">
            <WrapPanel>
                <TextBlock Text="{Binding Path=Key}"></TextBlock>
                <TextBlock Margin="0,0,4,0">: </TextBlock>
                <TextBlock Text="{Binding Path=Value}"></TextBlock>
            </WrapPanel>
        </DataTemplate>
        <DataTemplate x:Key="listViewData">
            <StackPanel>
                <WrapPanel Margin="0,0,0,8">
                    <TextBlock Margin="0,0,4,0">Section: </TextBlock>
                    <TextBlock Text="{Binding Path=Name}"/>
                </WrapPanel>
                <ListView ItemTemplate="{DynamicResource listViewData}" ItemsSource="{Binding Sections}" />
                <ListView ItemsSource="{Binding Attributes}" ItemTemplate="{StaticResource listViewAttr}" />
            </StackPanel>    
        </DataTemplate>
    </UserControl.Resources>
    <Grid>
        <ListView DataContext="{StaticResource ViewModel}" ItemTemplate="{DynamicResource listViewData}" ItemsSource="{Binding Sections}">
        </ListView>
    </Grid>
</UserControl>

This gets me basically what I want.

The main change is as Dan Bryant suggested: changing the ItemTemplate to use a Dynamic rather than static resource for the recursive object (Section).

忆离笙 2024-09-17 15:27:03

也许我误解了您的场景,但是 HierarchicalDataTemplate 你在找什么?

Perhaps I'm misunderstanding your scenario, but is HierarchicalDataTemplate what you're looking for?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文