ContentControl不会使用DataTemplates [英] ContentControl won't use DataTemplates

查看:102
本文介绍了ContentControl不会使用DataTemplates的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有两个要表示为目录和文件的模型。这两个模型都实现了一个包含属性 string Name {get;} 的接口。

I have two models that i want to represent as directories and files. The models both implement an interface which contains a property string Name {get;}.

public interface INode
{
    string Name { get; }
    string Path { get; }
}

public class Directory : INode
{
    public Directory(string name, string path)
    {
        this.Name = name;
        this.Path = path;
    }

    public string Name { get; }

    public string Path { get; }
}

public class File : INode
{
    public File(string name, string path)
    {
        this.Name = name;
        this.Path = path;
    }

    public string Name { get; }

    public string Path { get; }
}

我创建了两个 DataTemplates ,每个 INode 实现一个。每个模板都有一个 ContentControl 来呈现 Path ,以及一个 TextBlock 呈现 INode.Name 属性。

I created two DataTemplates, one for each INode implementation. Each template has a ContentControl to render a Path, and a TextBlock to render the INode.Name property.

<views:NavigationAwarePage
    x:Class="OpenTasks.Views.ProviderDirectoryBrowserPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:views="using:OpenTasks.Views"
    xmlns:models="using:OpenTasks.DomainLogic">

    <views:NavigationAwarePage.Resources>

        <DataTemplate x:Key="FolderIconTemplate">
            <Path Data="M10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6H12L10,4Z" 
                          Fill="{StaticResource AppTint}" 
                          HorizontalAlignment="Stretch"
                          VerticalAlignment="Stretch"
                          Width="96"
                          Height="96">
                <Path.RenderTransform>
                    <ScaleTransform ScaleX="2" ScaleY="2" />
                </Path.RenderTransform>
            </Path>
        </DataTemplate>
        <DataTemplate x:Key="FileIconTemplate">
            <Path Data="M13,9H18.5L13,3.5V9M6,2H14L20,8V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V4C4,2.89 4.89,2 6,2M11,4H6V20H11L18,20V11H11V4Z"
                          Fill="{StaticResource AppTint}" 
                          HorizontalAlignment="Stretch"
                          VerticalAlignment="Stretch"
                          Width="96"
                          Height="96">
                <Path.RenderTransform>
                    <ScaleTransform ScaleX="2" ScaleY="2" />
                </Path.RenderTransform>
            </Path>
        </DataTemplate>

        <DataTemplate x:DataType="models:Directory"
                              x:Key="DirectoryItemTemplate">
            <StackPanel Orientation="Horizontal">
                <ContentControl Content="{StaticResource FolderIconTemplate}" />
                <TextBlock Text="{Binding Path=Name}" />
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:DataType="models:File"
                              x:Key="FileItemTemplate">
            <StackPanel Orientation="Horizontal">
                <ContentControl Content="{StaticResource FileIconTemplate}" />
                <TextBlock Text="{Binding Path=Name}" />
            </StackPanel>
        </DataTemplate>
    </views:NavigationAwarePage.Resources>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ListView ItemsSource="{Binding Path=ContentsOfPath}" />
    </Grid>
</views:NavigationAwarePage>

然后将 ListView 绑定到 List< INode> 集合。但是,问题在于 ListView 仅呈现 INode <的 ToString()版本。 / code>实现,而不使用 DataTemplate

I then databound a ListView to a List<INode> collection. The problem however is that the ListView just renders the ToString() version of the INode implementation, instead of using the DataTemplate.

为什么 ListView 不能正确使用 DataTemplate <我已经定义了/ code> s?我还整理了一个 DataTemplateSelector ,但ListView仍然不使用我的模板之一。

Why does the ListView not properly use one of the DataTemplates I have defined? I have also put together a DataTemplateSelector, but the ListView still does not use one of my templates.

public class DirectoryListingTemplateSelector : DataTemplateSelector
{
    public DataTemplate DirectoryTemplate { get; set; }
    public DataTemplate FileTemplate { get; set; }

    protected override DataTemplate SelectTemplateCore(object item)
    {
        if (item is File)
        {
            return FileTemplate;
        }

        return DirectoryTemplate;
    }
}

<views:NavigationAwarePage.Resources>
    <views:DirectoryListingTemplateSelector x:Key="DirectoryListingSelector" 
                                        FileTemplate="{StaticResource FileItemTemplate}"
                                        DirectoryTemplate="{StaticResource DirectoryItemTemplate}" />


<ListView ItemsSource="{Binding Path=ContentsOfPath}"
            ItemTemplateSelector="{StaticResource DirectoryListingSelector}" />

执行 UWP 个应用处理 DataTemplate WPF 有所不同吗?我注意到即使指定 DataType ,也无法在没有指定键的情况下定义模板。我不确定其他可能导致我出现此问题的差异。这个确切的示例对我来说在WPF应用程序中运行良好,因此该问题特定于 UWP

Do UWP apps handle DataTemplates differently than WPF does? I've noticed I can't define a template without specifying a key, even if I specify a DataType. I'm not sure what other differences there may be that's causing this problem for me. This exact example is working fine for me in a WPF app, so the issue is specific to UWP.

我不确定为什么第一次尝试时它不起作用,但是模板选择器现在可以使用。我不想为每个可以支持多个模板的 ContentControl ItemsControl 写模板选择器。模板选择器是进入 UWP 的唯一方法吗?

I'm not sure why it wasn't working the first time I tried, but the template selector now works. I'd prefer not to write template selectors for every ContentControl or ItemsControl that can support more than one template. Are template selectors the only way to go in UWP?

<views:NavigationAwarePage
    x:Class="OpenTasks.Views.ProviderDirectoryBrowserPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:views="using:OpenTasks.Views"
    xmlns:models="using:OpenTasks.DomainLogic"
    xmlns:viewModels="using:OpenTasks.ViewModels"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    mc:Ignorable="d"
    d:DataContext="viewModels:ProviderDirectoryBrowserViewModelDesignData">

    <views:NavigationAwarePage.Resources>
        <views:DirectoryListingTemplateSelector x:Key="DirectoryListingSelector" 
                                                FileTemplate="{StaticResource FileItemTemplate}"
                                                DirectoryTemplate="{StaticResource DirectoryItemTemplate}" />

        <DataTemplate x:Key="FolderIconTemplate">
            <Path Data="M10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6H12L10,4Z" 
                  Fill="{StaticResource AppTint}" 
                  HorizontalAlignment="Stretch"
                  VerticalAlignment="Center"
                  Width="24"
                  Height="24" />
        </DataTemplate>
        <DataTemplate x:Key="FileIconTemplate">
            <Path Data="M13,9H18.5L13,3.5V9M6,2H14L20,8V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V4C4,2.89 4.89,2 6,2M11,4H6V20H11L18,20V11H11V4Z"
                  Fill="{StaticResource AppTint}" 
                  HorizontalAlignment="Stretch"
                  VerticalAlignment="Center"
                  Width="24"
                  Height="24" />
        </DataTemplate>

        <DataTemplate x:DataType="models:Directory"
                      x:Key="DirectoryItemTemplate">
            <StackPanel Orientation="Horizontal">
                <ContentControl ContentTemplate="{StaticResource FolderIconTemplate}"
                                VerticalAlignment="Center"
                                Margin="0 0 10 0"/>
                <TextBlock Text="{Binding Path=Name}"
                           VerticalAlignment="Center"/>
            </StackPanel>
        </DataTemplate>

        <DataTemplate x:DataType="models:File"
                      x:Key="FileItemTemplate">
            <StackPanel Orientation="Horizontal">
                <ContentControl ContentTemplate="{StaticResource FileIconTemplate}" 
                                Margin="0 0 10 0"
                                VerticalAlignment="Center"/>
                <TextBlock Text="{Binding Path=Name}"
                           VerticalAlignment="Center"/>
            </StackPanel>
        </DataTemplate>
    </views:NavigationAwarePage.Resources>

    <Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
        <ListView ItemsSource="{Binding Path=ContentsOfPath}"
                  ItemTemplateSelector="{StaticResource DirectoryListingSelector}" />
    </Grid>
</views:NavigationAwarePage>

推荐答案

我会说有几种方法可以解决此问题。对于您而言,我很想使用自定义转换器并为其分配图标模板。

I'd say there's a few ways to tackle this issue. In your case, I'd be tempted to use a custom converter and assign your icon templates to it.

转换器看起来像:

public class FileIconConverter : IValueConverter
{
    public DataTemplate FileIconTemplate { get; set; }

    public DataTemplate FolderIconTemplate { get; set; }

    public object Convert(object value, Type targetType, object parameter, string language)
    {
        if (value is Directory)
        {
            return this.FolderIconTemplate;
        }

        if (value is File)
        {
            return this.FileIconTemplate;
        }

        return null;
    }

    public object ConvertBack(object value, Type targetType, object parameter, string language)
    {
        throw new NotImplementedException();
    }
}

然后,在页面资源中创建转换器并分配图标模板:

Then, in the page resources, create the converter and assign the icon templates:

<local:FileIconConverter x:Key="FileIconConverter">
    <local:FileIconConverter.FileIconTemplate>
        <DataTemplate>
            <Path Data="M13,9H18.5L13,3.5V9M6,2H14L20,8V20A2,2 0 0,1 18,22H6C4.89,22 4,21.1 4,20V4C4,2.89 4.89,2 6,2M11,4H6V20H11L18,20V11H11V4Z"
                    Fill="{StaticResource AppTint}" 
                    HorizontalAlignment="Stretch"
                    VerticalAlignment="Stretch"
                    Width="96"
                    Height="96">
                <Path.RenderTransform>
                    <ScaleTransform ScaleX="2" ScaleY="2" />
                </Path.RenderTransform>
            </Path>
        </DataTemplate>
    </local:FileIconConverter.FileIconTemplate>
    <local:FileIconConverter.FolderIconTemplate>
        <DataTemplate>
            <Path Data="M10,4H4C2.89,4 2,4.89 2,6V18A2,2 0 0,0 4,20H20A2,2 0 0,0 22,18V8C22,6.89 21.1,6 20,6H12L10,4Z" 
                        Fill="{StaticResource AppTint}" 
                        HorizontalAlignment="Stretch"
                        VerticalAlignment="Stretch"
                        Width="96"
                        Height="96">
                <Path.RenderTransform>
                    <ScaleTransform ScaleX="2" ScaleY="2" />
                </Path.RenderTransform>
            </Path>
        </DataTemplate>
    </local:FileIconConverter.FolderIconTemplate>
</local:FileIconConverter>

最后,在您的列表视图中,绑定数据并使用转换器:

Lastly, in your listview, bind your data and use the converter:

<ListView x:Name="ListView">
    <ListView.ItemTemplate>
        <DataTemplate>
            <StackPanel Orientation="Horizontal">
                <ContentControl ContentTemplate="{Binding Converter={StaticResource FileIconConverter}}" 
                            Margin="0 0 10 0"
                            VerticalAlignment="Center"/>
                <TextBlock Text="{Binding Path=Name}"
                        VerticalAlignment="Center"/>
            </StackPanel>
        </DataTemplate>
    </ListView.ItemTemplate>
</ListView>

这篇关于ContentControl不会使用DataTemplates的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆