WPF ListView within a ListView

2020-07-18 03:09发布

问题:

I am sure I am missing something simple/obvious, but I cannot seem to bind the data of a ListView within a ListView

<Window x:Class="TestList.MainWindow"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="MainWindow" Height="350" Width="525">
<Window.Resources>
    <DataTemplate x:Key="InsideListTemplate">
        <StackPanel Orientation="Horizontal">
            <TextBlock Text="test" Width="50"></TextBlock>
            <TextBlock Text="{Binding OrderId}" Width="50"></TextBlock>
        </StackPanel>
    </DataTemplate>
    <DataTemplate x:Key="OrdersTemplate">
        <ListView HorizontalAlignment="Stretch"
                  HorizontalContentAlignment="Stretch"
                  MinWidth="100"
                  MinHeight="25"
            ItemsSource="{Binding Orders}" 
            ItemTemplate="{StaticResource InsideListTemplate}" 
        >
        </ListView>
    </DataTemplate>
    <DataTemplate x:Key="CustomersTemplate">
        <StackPanel Orientation="Horizontal" HorizontalAlignment="Stretch">
            <TextBlock Text="{Binding CustomerId}" Width="50" Foreground="Navy" VerticalAlignment="Center" />
            <ListBox ItemsSource="{Binding Orders}" ItemTemplate="{StaticResource OrdersTemplate}" HorizontalContentAlignment="Stretch"></ListBox>
        </StackPanel>
    </DataTemplate>

</Window.Resources>
<DockPanel LastChildFill="True">
    <ListView Name="listView" ItemTemplate="{StaticResource CustomersTemplate}" >
    </ListView>
</DockPanel>

using System.Collections.Generic;
namespace TestList
{
public partial class MainWindow
{
    public class Customer
    {
        public int CustomerId { get; set; }
        public List<Order> Orders { get; set; }
    }

    public class Order
    {
        public int OrderId { get; set; }
    }
    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        var customers = new List<Customer>
                            {
                                new Customer
                                    {
                                        CustomerId = 1,
                                        Orders = new List<Order>
                                                     {
                                                         new Order {OrderId = 1},
                                                         new Order {OrderId = 2}
                                                     }
                                    },
                                new Customer
                                    {
                                        CustomerId = 2,
                                        Orders = new List<Order>
                                                     {
                                                         new Order {OrderId = 1},
                                                         new Order {OrderId = 2}
                                                     }
                                    }
                            };
        listView.ItemsSource = customers;
    }
  }
}

回答1:

This is an explanation of Hadis answer:

You are binding a ListBox to the Orders collection within the customer template. And then in the orders template you define a ListView binding again to the orders. This means that the binding path at that point is customer.orders.orders which does not exists.

If you just remove the OrdersTemplate and place the ListView where the ListBox is in the customer template then it works.



回答2:

How about changing it list this:

public partial class MainWindow : Window
{
    public class Customer
    {
        public int CustomerId { get; set; }
        public List<Order> Orders { get; set; }
    }

    public class Order
    {
        public int OrderId { get; set; }
        public List<OrderItem> Items { get; set; }
    }

    public class OrderItem
    {
        public int No { get; set; }
        public string Name { get; set; }
    }

    public MainWindow()
    {
        InitializeComponent();
        DataContext = this;
        var customers = new List<Customer>
        {
            new Customer
            {
                CustomerId = 1,
                Orders = new List<Order>
                {
                    new Order {OrderId = 1, Items = new List<OrderItem>(new[] { new OrderItem { Name = "CD Player", No = 1}, new OrderItem { Name = "VCR Player", No = 2} })},
                    new Order {OrderId = 2, Items = new List<OrderItem>(new[] { new OrderItem { Name = "DVD Player", No = 1} })}
                }
            },
            new Customer
            {
                CustomerId = 2,
                Orders = new List<Order>
                {
                    new Order {OrderId = 1},
                    new Order {OrderId = 2}
                }
            }
        };
        listView.ItemsSource = customers;
    }
}

and on your Xaml modify it like this:

<DataTemplate x:Key="InsideListTemplate">
    <StackPanel Orientation="Horizontal">
        <TextBlock Text="{Binding No}" Width="50"></TextBlock>
        <TextBlock Text="{Binding Name}" Width="50"></TextBlock>
    </StackPanel>
</DataTemplate>
<DataTemplate x:Key="OrdersTemplate">
    <StackPanel>
        <TextBlock Text="{Binding OrderId}" />
        <ListView HorizontalAlignment="Stretch"
              HorizontalContentAlignment="Stretch"
              MinWidth="100"
              MinHeight="25"
              ItemsSource="{Binding Items}" 
              ItemTemplate="{StaticResource InsideListTemplate}" />
    </StackPanel>
</DataTemplate>

And your output will display the details