如何使用递归对象作为主要数据源在列表视图中设置列表视图的 ItemsSource?
how to set the ItemsSource of a listview in a listview, using a recursive object as main datasource?
由一位好心人解决,他让我意识到我需要更彻底地调试。我在这里提出的代码确实有效。
几天来我一直在努力解决这个问题,起初看起来很简单,但我一直没能做到。
我有一个包含自身集合的对象:
public class Car: ViewModelBase
{
private string _name;
public string Name { get { return _name; } set { Set(ref _name, value); } }
private ObservableCollection<Car> _carCollection = new ObservableCollection<Car>();
public ObservableCollection<Car> CarCollection { get { return _carCollection; } set { Set(ref _carCollection, value); } }
}
在我的 ViewModel 中,我定义了一个对象实例:
public class RecipesViewModel:ViewModelBase
{
private Car _car;
public Car Car { get { return _car; } set { Set(ref _car, value); } }
//User populates the name prop and the list within car (level 1 data),
//and adds a number of objects to the list within the level 1 list (level 2 data)
}
在 view/XAML 中,我使用 Itemtemplate 和数据源设置了一个列表:
<Page
x:Class="CarProject.Views.CarPage"
DataContext="{Binding CarViewModel, Source={StaticResource Locator}}"
...
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<CollectionViewSource Source="{x:Bind ViewModel.Car.CarCollection, Mode=OneWay}"
x:Key="CarListSource"
IsSourceGrouped="False"/>
</ResourceDictionary>
</Page.Resources>
<Grid>
<ListView x:Name="CarList"
ItemsSource ="{Binding Source={StaticResource RecipeSingleAromaListSource}, Mode=OneWay}" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Car" x:Name="CarItem" >
<StackPanel>
<TextBlock Text="{x:Bind Name}"/>
<ListView x:Name="Level2Sublist"
ItemsSource="{Binding CarCollection"}>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
我已经为 "Level2SubList" 尝试了 RelativeSource 和 ItemsSource 定义的许多排列,但我似乎无法引用 level2 汽车集合。
无论我做什么,"Level2SubList" 都保持空白。
我一直在网上搜索,但没有找到类似的用例。也许我需要上一堂使用 Google 的课程,因为我不可能是唯一一个尝试过这个的人:)
谢谢!
P.S。
class 和 XAML 列表包含许多其他属性,为了便于阅读,我对其进行了简化
内部 DataTemplate
没有 x:DataType
属性,如果您使用 x:Bind
:
<DataTemplate x:DataType="models:Car">
...
</DataTemplate>
然后,为了实际显示汽车的 Name
,您使用的是 TextBlock
的 Name
属性,但这实际上设置了 XAML 姓名。你需要 Text
属性:
<TextBlock Text="{x:Bind Name}" />
更新
除了这些问题之外,代码对我有用。在一个空白的 UWP 项目中尝试以下操作(我的名字是 App3
):
MainPage.xaml
<Page
x:Class="App3.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App3"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<ListView x:Name="CarList"
ItemsSource="{x:Bind Car.CarCollection}" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Car" x:Name="CarItem" >
<StackPanel>
<TextBlock Text="{x:Bind Name}"/>
<ListView x:Name="Level2Sublist"
ItemsSource="{Binding CarCollection}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>
MainPage.xaml.cs
using System.Collections.ObjectModel;
using Windows.UI.Xaml.Controls;
namespace App3
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
public Car Car { get; } = new Car()
{
CarCollection = new ObservableCollection<Car>()
{
new Car(){Name = "A", CarCollection = new ObservableCollection<Car>(){ new Car(){Name="A1"}, new Car(){Name="A2" } } },
new Car(){Name = "B", CarCollection = new ObservableCollection<Car>(){ new Car(){Name="B1"}, new Car(){Name="B2" }, new Car(){Name="B3" } }}
}
};
}
public class Car
{
public string Name { get; set; }
public ObservableCollection<Car> CarCollection { get; set; }
}
}
您可以看到应用甚至显示嵌套列表:
由一位好心人解决,他让我意识到我需要更彻底地调试。我在这里提出的代码确实有效。
几天来我一直在努力解决这个问题,起初看起来很简单,但我一直没能做到。
我有一个包含自身集合的对象:
public class Car: ViewModelBase
{
private string _name;
public string Name { get { return _name; } set { Set(ref _name, value); } }
private ObservableCollection<Car> _carCollection = new ObservableCollection<Car>();
public ObservableCollection<Car> CarCollection { get { return _carCollection; } set { Set(ref _carCollection, value); } }
}
在我的 ViewModel 中,我定义了一个对象实例:
public class RecipesViewModel:ViewModelBase
{
private Car _car;
public Car Car { get { return _car; } set { Set(ref _car, value); } }
//User populates the name prop and the list within car (level 1 data),
//and adds a number of objects to the list within the level 1 list (level 2 data)
}
在 view/XAML 中,我使用 Itemtemplate 和数据源设置了一个列表:
<Page
x:Class="CarProject.Views.CarPage"
DataContext="{Binding CarViewModel, Source={StaticResource Locator}}"
...
mc:Ignorable="d">
<Page.Resources>
<ResourceDictionary>
<CollectionViewSource Source="{x:Bind ViewModel.Car.CarCollection, Mode=OneWay}"
x:Key="CarListSource"
IsSourceGrouped="False"/>
</ResourceDictionary>
</Page.Resources>
<Grid>
<ListView x:Name="CarList"
ItemsSource ="{Binding Source={StaticResource RecipeSingleAromaListSource}, Mode=OneWay}" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="models:Car" x:Name="CarItem" >
<StackPanel>
<TextBlock Text="{x:Bind Name}"/>
<ListView x:Name="Level2Sublist"
ItemsSource="{Binding CarCollection"}>
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
我已经为 "Level2SubList" 尝试了 RelativeSource 和 ItemsSource 定义的许多排列,但我似乎无法引用 level2 汽车集合。 无论我做什么,"Level2SubList" 都保持空白。
我一直在网上搜索,但没有找到类似的用例。也许我需要上一堂使用 Google 的课程,因为我不可能是唯一一个尝试过这个的人:)
谢谢!
P.S。 class 和 XAML 列表包含许多其他属性,为了便于阅读,我对其进行了简化
内部 DataTemplate
没有 x:DataType
属性,如果您使用 x:Bind
:
<DataTemplate x:DataType="models:Car">
...
</DataTemplate>
然后,为了实际显示汽车的 Name
,您使用的是 TextBlock
的 Name
属性,但这实际上设置了 XAML 姓名。你需要 Text
属性:
<TextBlock Text="{x:Bind Name}" />
更新
除了这些问题之外,代码对我有用。在一个空白的 UWP 项目中尝试以下操作(我的名字是 App3
):
MainPage.xaml
<Page
x:Class="App3.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:App3"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid>
<ListView x:Name="CarList"
ItemsSource="{x:Bind Car.CarCollection}" >
<ListView.ItemTemplate>
<DataTemplate x:DataType="local:Car" x:Name="CarItem" >
<StackPanel>
<TextBlock Text="{x:Bind Name}"/>
<ListView x:Name="Level2Sublist"
ItemsSource="{Binding CarCollection}">
<ListView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}"/>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
</Grid>
</Page>
MainPage.xaml.cs
using System.Collections.ObjectModel;
using Windows.UI.Xaml.Controls;
namespace App3
{
public sealed partial class MainPage : Page
{
public MainPage()
{
this.InitializeComponent();
}
public Car Car { get; } = new Car()
{
CarCollection = new ObservableCollection<Car>()
{
new Car(){Name = "A", CarCollection = new ObservableCollection<Car>(){ new Car(){Name="A1"}, new Car(){Name="A2" } } },
new Car(){Name = "B", CarCollection = new ObservableCollection<Car>(){ new Car(){Name="B1"}, new Car(){Name="B2" }, new Car(){Name="B3" } }}
}
};
}
public class Car
{
public string Name { get; set; }
public ObservableCollection<Car> CarCollection { get; set; }
}
}
您可以看到应用甚至显示嵌套列表: