创建一个DataTemplate,其中包含另一个使用第一个数据源的DataTemplate

时间:2014-10-01 14:12:58

标签: wpf binding datacontext

所以,我的想法是,我有一个ListView使用Template1作为DataTemplate,然后包含另一个ListView Template2,使用Cars第一个DataContext的绑定/ datacontext。因此Template2的{​​{1}}应该是Template1 DataContext.Cars,应该用作DataTemplate2的绑定。

有可能吗?怎么???

型号:

class Reseller 
{
    public Dictionary<int, Car> Cars;
    ...
}

class Car 
{
    public string Model { get; set; }
    public string Year { get; set; }
    ...
}

我有两个这样的DataTemplates:

<!--Template1 contains a Dictionary<string, Reseller>-->
<!-- Reseller has another dictionary of Cars like Dictionary<int, Car>-->
<DataTemplate x:Key="Template1">
    <StackPanel Orientation="Horizontal">
        <GroupBox Header="{Binding Key}">
            <ListView x:Name="Internal_Template2
                      ItemTemplate="{StaticResource Template2}"/>
        </GroupBox>
    </StackPanel>
</DataTemplate>

<DataTemplate x:Key="Template2">
    <Grid>
        <TextBlock Text="{Binding Template1.Value.Cars.Model}"/>
        <TextBlock Text="{Binding Template1.Value.Cars.Year}"/>
    </Grid>
</DataTemplate>

这是我想要创建的内容的快速绘图。 BranchX是一个ListView,它包含Cars,这是另一个`ListView,来自BranchX的Cars属性: enter image description here

2 个答案:

答案 0 :(得分:2)

是的,这是可能的。我将向您展示根据我的项目改编的示例,其中我在另一个ItemsControl中使用ItemsControl。这可以适用于除ItemsControl之外的其他容器,但ItemsControl提供了最大的灵活性。 如果我理解正确,您希望显示经销商列表,并且对于每个经销商,您希望显示汽车列表。

对于每个 ResellerInfo 项,外部ItemsControl将显示一个带有TextBlock的StackPanel和另一个显示Cars的ItemsControl。

然后,内部ItemsControl会显示每个车辆的模型和年份的StackPanel。请注意,内部的DataContext会自动设置为 CarInfo 的实例。

作为奖励,我们正在使用VirtualizingStackPanel,它不会渲染屏幕外的项目 - 如果您的数据库很大,这可以派上用场。

作为主控件的 DataContext 的viewmodel需要定义:

public ObservableCollection<ResellerInfo> Resellers

ResellerInfo 是一个具有以下属性的类:

public String ResellerName
public ObservableCollection<CarInfo> Cars

CarInfo 是一个具有以下属性的类:

public String Model
public String Year

需要调用所有属性的setter

NotifyPropertyChanged();

INotifyPropertyChanged接口

中定义

XAML:

        <ItemsControl ItemsSource="{Binding Resellers}" >
            <!-- Template specifies how this ItemsControl looks like -->
            <ItemsControl.Template>
                <ControlTemplate TargetType="ItemsControl">
                    <ScrollViewer Margin="5">
                        <ItemsPresenter />
                    </ScrollViewer>
                </ControlTemplate>
            </ItemsControl.Template>
            <!-- ItemsPanel holds items. Use it to change the way items are laid out -->
            <ItemsControl.ItemsPanel>
                <ItemsPanelTemplate>
                    <VirtualizingStackPanel VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" Orientation="Horizontal" />
                </ItemsPanelTemplate>
            </ItemsControl.ItemsPanel>
            <!-- ItemTemplate specifies how each item is displayed -->
            <ItemsControl.ItemTemplate>
                <DataTemplate>
                    <!-- BEGINNING OF SINGLE ITEM CODE -->
                    <StackPanel>
                        <TextBlock Text="{Binding ResellerName}" />
                        <ItemsControl ItemsSource="{Binding Cars}">
                            <!-- Template specifies how this ItemsControl looks like -->
                            <ItemsControl.Template>
                                <ControlTemplate TargetType="ItemsControl">
                                    <ScrollViewer Margin="5">
                                        <ItemsPresenter />
                                    </ScrollViewer >
                                </ControlTemplate>
                            </ItemsControl.Template>
                            <!-- ItemsPanel holds items. Use it to change the way items are laid out -->
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <VirtualizingStackPanel VirtualizingPanel.IsVirtualizing="True" VirtualizingPanel.VirtualizationMode="Recycling" Orientation="Horizontal" />
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                            <!-- ItemTemplate specifies how each item is displayed. -->
                            <ItemsControl.ItemTemplate>
                                <DataTemplate>
                                    <StackPanel>
                                        <TextBlock Text="{Binding Model}" />
                                        <TextBlock Text="{Binding Year}" />
                                    </StackPanel>
                                <DataTemplate>
                            </ItemsControl.ItemTemplate> -->
                        </ItemsControl>
                    </StackPanel>
                    <!-- END OF SINGLE ITEM CODE -->
                </DataTemplate>
            </ItemsControl.ItemTemplate>
        </ItemsControl>

我在StackOverflow上编写了代码,如果您发现错误,请随时更正!

答案 1 :(得分:1)

ListView 中分配 ItemsSource (我假设您在代码隐藏中执行此操作)时,每个项目的 DataContext 设置为他们的模型表示。例如:

ListView (DataContext: Resellers)
|-- ListViewItem (DataContext: Resellers[0])
|-- ListViewItem (DataContext: Resellers[1])
`-- etc...

因此您无需访问父 DataTemplate DataContext 。实际上, Template2 DataContext 会自动设置为Resellers[].Value.Cars[]。这允许您将 TextBlock 绑定到Value

<DataTemplate x:Key="Template2">
    <Grid>
        <TextBlock Text="{Binding Value.Model}"/>
        <TextBlock Text="{Binding Value.Year}"/>
    </Grid>
</DataTemplate>

<DataTemplate x:Key="Template1">
    <GroupBox Header="{Binding Key}">
        <ListView x:Name="Internal_Template2
                  ItemsSource="{Binding Value.Cars}"
                  ItemTemplate="{StaticResource Template2}"/>
    </GroupBox>
</DataTemplate>

您无法让 ListView ItemTemplate 中显示其项目水平,您需要将 ItemsPanel 属性添加到您的转销商的ListView

<ListView.ItemsPanel>
    <ItemsPanelTemplate>
        <StackPanel
            Orientation="Horizontal" />
    </ItemsPanelTemplate>
</ListView.ItemsPanel>