【问题标题】:Create a DataTemplate that contains another DataTemplate which use data source from the first创建一个包含另一个 DataTemplate 的 DataTemplate,该 DataTemplate 从第一个开始使用数据源
【发布时间】:2014-11-26 09:59:37
【问题描述】:

所以,我的想法是我有一个ListView,它使用Template1 作为DataTemplate,然后包含另一个ListViewTemplate2,它使用第一个Cars 的绑定/数据上下文.所以DataContextTemplate2 应该是Template1 DataContext.Cars 应该用作DataTemplate2 的绑定。

有可能吗?怎么样???

型号:

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

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

我有两个这样的数据模板:

<!--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 属性:

【问题讨论】:

    标签: wpf binding datacontext


    【解决方案1】:

    ListView 中分配 ItemsSource(我假设您在代码隐藏中这样做)时,每个项目的 DataContext 都设置为它们的模型表示。例如:

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

    所以你不需要访问父DataTemplateDataContext。实际上,Template2DataContext 自动设置为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>
    

    您无法使 ListViewItemTemplate 中水平显示其项目,您需要将 ItemsPanel 属性添加到您的 Reseller 列表视图

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

    【讨论】:

    • 感谢您的贡献。这很简单,也是我使用的解决方案。您也可以传递数据源,这太棒了,完全忘记了! :) 我只需要记住,属性需要是公共的,以及字符串或 int 的类型。
    【解决方案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 上编写了代码,如果您发现错误,请随时纠正!

    【讨论】:

    • 感谢您的贡献。毫无疑问,VirtualizingPanel 的解决方案很好。我使用了@hantoun 的示例,因为 UI 仅用于调试,并且该示例非常简单。但是您的解决方案也解决了我的问题:)
    • 与我发布的解决方案相比,此解决方案是更好的做法。我刚刚详细说明了您已经拥有的代码。
    • @hantoun 您的解决方案肯定更好地回答了这个问题。其实我不知道这么简单的代码就可以做到!
    猜你喜欢
    • 1970-01-01
    • 2013-06-28
    • 1970-01-01
    • 2017-10-17
    • 2011-03-05
    • 2011-08-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多