【问题标题】:How to display a recursive property in XAML如何在 XAML 中显示递归属性
【发布时间】:2016-04-22 08:16:07
【问题描述】:

我有一门课,看起来像

public class MyClass 
{
    public string MyTitle{get;set;}
    public MyClass Child{get;set;
}

这样做的原因是孩子和父母之间永远只有一对一的关系(也就是说,没有父母会有多个孩子)。

我想在 WPF 应用程序中进行布局,其中每个 MyTitle 将水平显示(基于总共有多少父和子)。 EG,类似

MyClass.MyTitle       MyClass.Child.MyTitle       MyClass.Child.Child.MyTitle  etc

在网络世界中,我们可以添加循环和 if 语句,只需检查子项是否为空(或不为空),然后附加下一项。

在网络世界中,类似于(伪代码)

item = Model.MyClass;

do while(true) {    
    if (item != null) {
        <div class="floatLeft">item.MyTitle</div>
    }
    else {
        break;
    }
    item = parent.Child;
}

XAML 似乎将我限制为模板。虽然我确信我会制定一个 C# 解决方案然后直接绑定,但我正在利用这个机会来了解有关 XAML 的更多信息。

问题是,它不是一个列表,所以我不确定使用 ItemsControl/ListView/etc 是否是正确的方法。我什至不确定我想要的能不能做到。

所以我的问题是这可以仅使用 XAML 完成吗?

【问题讨论】:

    标签: c# wpf xaml


    【解决方案1】:

    如下所示的简单 DataTemplate 就可以完成这项工作。通过设置它的DataType属性,当Content的类型匹配DataType时,它会自动应用到ContentPresenters,ContentControls等的Content,这也将递归工作。

    <Window.Resources>
        <DataTemplate DataType="{x:Type local:MyClass}">
            <StackPanel Orientation="Horizontal">
                <TextBlock Margin="4" Text="{Binding MyTitle}"/>
                <ContentPresenter Content="{Binding Child}"/>
            </StackPanel>
        </DataTemplate>
    </Window.Resources>
    

    鉴于您的窗口的 DataContext 包含一个 MyClass 实例,您可以只写

    <ContentControl Content="{Binding}"/>
    

    DataTemplate 会自动递归应用。

    您可以尝试设置 DataContext 之类的

    DataContext = new MyClass
    {
        MyTitle = "Item1",
        Child = new MyClass
        {
            MyTitle = "Item2",
            Child = new MyClass
            {
                MyTitle = "Item3",
            }
        }
    };
    

    【讨论】:

    • 你会建议 DataTemplate 去哪里?
    • 在答案中,DataTemplate 位于窗口的资源中。 ContentControl 位于窗口的 XAML 中,并假定 Window 的 DataContext 包含一个 MyClass 实例。
    • 哦,对不起。我现在知道了。阅读您的代码对我来说还没有意义(在我看来,它必须使用某种显然没有的中继器)所以请给我几分钟的时间来测试和玩? :)
    • 小修改:我用 ContentPresenter 替换了 DataTemplate 中的 ContentControl。见这里:stackoverflow.com/a/1288353/1136211
    • 这很好,但是是否可以使用 StaticResource 和键来命名 DataTemplate 并从 ContentControl 中引用它?另外,你为什么改用 ContentPresenter,因为它与 ContentControl 一起使用?
    【解决方案2】:

    如果 MyClass 总是有固定数量的子 MyClass 元素,则可以制作递归模板

    <Window x:Class="WpfApplication2.TestWindow"
            xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
            xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
            xmlns:wpfApplication2="clr-namespace:WpfApplication2"
            Title="TestWindow" Height="300" Width="300">
        <Window.Resources>
        <DataTemplate DataType="{x:Type wpfApplication2:MyClass}">
            <WrapPanel Orientation="Horizontal">
                <TextBlock Text=" => " FontSize="18" Margin="5,0"/>
                <TextBlock Text="{Binding MyTitle}" FontSize="18"/>
                <ContentControl Content="{Binding Child}"/>
            </WrapPanel>
        </DataTemplate>    
    
        </Window.Resources>
    
        <Grid>
          <Border BorderBrush="Blue" BorderThickness="1" 
                Margin="5" VerticalAlignment="Top">
            <ContentControl Content="{Binding .}"/>
          </Border>
        </Grid>
    </Window>
    
    public partial class TestWindow : Window
    {
        public TestWindow()
        {
            InitializeComponent();
            // test DataContext
            DataContext = new MyClass
            {
                MyTitle = "1234567890",
                Child = new MyClass
                {
                    MyTitle = "qwerty uiop ",
                    Child = new MyClass
                    {
                        MyTitle = "asdf ghjkl"
                    }
                }
            };
        }
    }
    

    【讨论】:

    • 你写了1 to 1 relationship。这意味着任何给定的 MyClass 实例都有 1 个孩子。怎么了?树的高度可以变化,但模板会处理它
    • @MyDaftQuestions 子元素没有“固定”是什么意思?
    猜你喜欢
    • 2020-11-16
    • 1970-01-01
    • 2011-07-21
    • 1970-01-01
    • 2013-11-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多