【问题标题】:WPF/XAML using TreeViewItems in a TreeView with Databinding and advanced templatesWPF/XAML 在具有数据绑定和高级模板的 TreeView 中使用 TreeViewItems
【发布时间】:2012-12-08 12:50:52
【问题描述】:

我对 XAML 和数据绑定还很陌生,所以希望这对那里的人来说是一个简单的问题...

我正在尝试使用具有类似结构的数据绑定来构建 TreeView:

  • 类别
    • 项目名称
    • 项目名称
  • 类别
    • 项目名称

到目前为止,一切都很好——我可以做到。接下来,我希望能够展开 Item 节点并显示有关该项目的详细信息。当我在代码隐藏中手动构建树时,这很好用,但我想改用数据绑定。我几乎有这个工作,但现在,要么我无法选择节点,要么我无法让节点表现得像 TreeViewItem,它在折叠时只显示项目名称并且可以展开以显示更多--在我的例子中是一个自定义的网格,上面有数据。

这是我的 XAML 代码的简化示例:

<DataTemplate x:Key="ItemDataTemplate">
    <TreeViewItem Header="{Binding Path=ItemName}">
        <Grid>
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="Auto"/>
                <ColumnDefinition Width="*"/>
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition />
                <RowDefinition />
                <RowDefinition />
            </Grid.RowDefinitions>

            <TextBlock Grid.Row="0" Grid.Column="0" Text="Price" />
            <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=Price}"/>

            <TextBlock Grid.Row="1" Grid.Column="0" Text="Description" />
            <TextBlock Grid.Row="1" Grid.Column="1" Text="{Binding Path=Description}"/>

            <TextBlock Grid.Row="2" Grid.Column="0" Text="Qty on Hand" />
            <TextBlock Grid.Row="2" Grid.Column="1" Text="{Binding Path=Qty}"/>
        </Grid>
    </TreeViewItem>
</DataTemplate>

<HierarchicalDataTemplate x:Key="CategoryDataTemplate" ItemsSource="{Binding Path=Categories}" ItemTemplate="{StaticResource ItemDataTemplate}">
    <TextBlock Text="{Binding Path=CategoryName}"/>
</HierarchicalDataTemplate>

基于这个简化的示例,在代码隐藏中定义的对象将是这样的:

public class Category
{
    public ObservableCollection<Item> Items {get; private set;}
    public string CategoryName { get; set; }

    //constructor and methods here
}
public class Item
{
    public string ItemName {get; private set;}
    public decimal Price { get; private set; }
    public string Description {get; private set; }
    public int Qty {get; set;}

    //constructor and methods here
}

在 stackoverflow 上阅读 this question and answer 后,我可以看到如果您想选择节点,您的模板不能是 TreeViewItem。我尝试摆脱 TreeViewItem 标记并直接进入允许我选择节点的网格,但现在我无法将节点折叠到仅 ItemName(标题文本)。

我觉得它非常接近......我错过了什么?

【问题讨论】:

    标签: wpf xaml templates binding treeview


    【解决方案1】:

    那么,您想要的是让一个 Item 看起来像它有更多的子节点,即使它唯一的“子”是它自己,并提供更多信息?

    嗯,最正确的做法可能是在 ItemDataTemplate 中使用扩展器,如下所示:

    <DataTemplate x:Key="ItemDataTemplate">
        <Expander Header="{Binding Path=ItemName}" >
            <Grid>
                <Grid.ColumnDefinitions>
                    ...
                <Grid.RowDefinitions>
                    ...
    
                <TextBlock Grid.Row="0" Grid.Column="0" Text="Price" />
                <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=Price}"/>
    
                <TextBlock ...
            </Grid>
        </TreeViewItem>
    </DataTemplate>
    

    扩展器看起来并不完全像标准的 TreeViewItem,但可以通过为扩展器制作自己的模板来解决这个问题。

    现在,一个稍微有点笨拙的方法是在 Item 类中拥有一个 Items 列表,其中每个 Item 将自己暴露为唯一的列表元素。然后,ItemDataTemplate 需要是一个 HierarchicalDataTemplate,它引用了另一个更详细的“ItemDetailsTemplate”:

    public class Item
    {
        ...
    
        public List<Item> InfoWrapper
        {
            get { return new List<Item>() { this }; }
        }
    }
    

    Xaml:

    <DataTemplate x:Key="ItemDetailsTemplate">
        <Grid>
            <Grid.ColumnDefinitions>
                ...
            <Grid.RowDefinitions>
                ...
    
            <TextBlock Grid.Row="0" Grid.Column="0" Text="Price" />
            <TextBlock Grid.Row="0" Grid.Column="1" Text="{Binding Path=Price}"/>
    
            <TextBlock ...
        </Grid>
    </DataTemplate>
    
    <HierarchicalDataTemplate x:Key="ItemDataTemplate" ItemsSource="{Binding Path=InfoWrapper}" ItemTemplate="{StaticResource ItemDetailsTemplate}" >
        <TextBlock Text="{Binding Path=ItemName}"/>
    </HierarchicalDataTemplate>
    

    【讨论】:

    • 您的“更老套的做法”正是我想要的——谢谢!我也喜欢您关于使用扩展器并使其看起来和感觉像带有模板的 TreeViewItem 的建议——我将不得不深入研究一下如何做到这一点。我同意扩展器可能是一种更正确的方法,所以如果我能弄清楚,我可能会切换到那个方法。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-03-14
    相关资源
    最近更新 更多