在其他数据模板中重用UWP XAML数据模板

时间:2018-07-01 03:14:27

标签: c# twitter uwp datatemplate uwp-xaml

我不太确定该如何表达自己的意思,因此,如果有任何不清楚之处,请事先道歉。

我正在用UWP C#编写一个Twitter客户端。我需要做的一件事情是控制一系列tweet中的每个tweet的DataTemplate(由Twitter的API返回)。我遇到的问题是,如果我为每种tweet类型制作一个单独的DataTemplate,那么我将得到很多相同的代码。这是因为推文可以是任何类型的推文组合(文本,图像,视频,GIF,URL,转发和带引号的转发)。

不必为每个可能的组合复制相同的DataTemplate,而是可以在不同的tweet类型之间重用主Tweet模板吗?

对于转推和引用推文,该tweet对象包含一个嵌套的第二个tweet对象(对于转推或引用tweet,又名retweet +文本),但是我不知道如何以任何方式传递该第二个tweet对象让我可以重复使用现有模板。

这是我现在拥有的DataTemplates的一个示例-到目前为止,我只做过推文和转推。 RetweetTemplate与TweetTemplate几乎相同,除了在网格顶部的“ @username retweeted”文本多了一行,并且绑定指向Tweet.RetweetedStatus而不是Tweet。

那么有什么办法可以减少冗余代码呢?还是我坚持为每种可能的组合制作几乎重复的模板以容纳媒体并通过媒体转发了推文?

<DataTemplate x:Key="TweetTemplate">
    <Grid MinHeight="150" Width="450" BorderBrush="{ThemeResource SystemControlDisabledListMediumBrush}" BorderThickness="1" Margin="-12 0" Padding="10 5">
        <Grid.RowDefinitions>
            <RowDefinition Height="30"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="40"/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <StackPanel Orientation="Horizontal" Padding="5">
                <TextBlock Text="{Binding Path=User.Name}" Margin="0 0 8 0"  FontWeight="Bold" />
                <TextBlock Text="{Binding Path=User.ScreenName, Converter={StaticResource GetHandle}}" Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}" />
                <TextBlock Text="&#x2981;" Margin="8 0" />
                <TextBlock Text="{Binding CreationDate, Converter={StaticResource FormatDate}}" />
            </StackPanel>
        </Grid>
        <Grid Grid.Row="1">
            <TextBlock Text="{Binding Text}" Padding="5" TextWrapping="WrapWholeWords" />
        </Grid>
        <Grid Grid.Row="2">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="2.5*" MaxWidth="100"/>
                <ColumnDefinition Width="2.5*"/>
                <ColumnDefinition Width="2.5*"/>
                <ColumnDefinition Width="2.5*"/>
            </Grid.ColumnDefinitions>
            <Grid Grid.Column="0">
                <Button x:Name="cmdComment" Content="&#xf075;" Style="{StaticResource MetaButtons}" />
            </Grid>
            <Grid Grid.Column="1">
                <Button x:Name="cmdRetweet" Content="&#xf079;" Style="{StaticResource MetaButtons}" />
            </Grid>
            <Grid Grid.Column="2">
                <Button x:Name="cmdLike" Content="&#xf004;" Style="{StaticResource MetaButtons}" />
            </Grid>
            <Grid Grid.Column="3">
                <Button x:Name="cmdMessage" Content="&#xf0e0;" Style="{StaticResource MetaButtons}" />
            </Grid>
        </Grid>
    </Grid>
</DataTemplate>

<DataTemplate x:Key="RetweetTemplate">
    <Grid MinHeight="150" MinWidth="420">
        <Grid.RowDefinitions>
            <RowDefinition Height="28"/>
            <RowDefinition Height="30"/>
            <RowDefinition Height="*"/>
            <RowDefinition Height="40"/>
        </Grid.RowDefinitions>
        <Grid Grid.Row="0">
            <StackPanel Orientation="Horizontal" Padding="4 8 4 0">
                <StackPanel.Resources>
                    <Style TargetType="TextBlock">
                        <Setter Property="FontSize" Value="12"/>
                        <Setter Property="Foreground" Value="{ThemeResource SystemControlPageTextBaseMediumBrush}" />
                    </Style>
                </StackPanel.Resources>
                <Border Height="28">
                    <TextBlock Height="24" FontFamily="{StaticResource FontAwesome}" xml:space="preserve"><Run Text="&#xf079;&#160;"/></TextBlock>
                </Border>                    
                <TextBlock Text="{Binding Path=User.Name}" />
                <TextBlock Text=" retweeted"/>
            </StackPanel>
        </Grid>
        <Grid Grid.Row="1">
            <StackPanel Orientation="Horizontal" Padding="5">
                <TextBlock Text="{Binding Path=RetweetedStatus.User.Name}" Margin="0 0 8 0"  FontWeight="Bold" />
                <TextBlock Text="{Binding Path=RetweetedStatus.User.ScreenName, Converter={StaticResource GetHandle}}" Foreground="{ThemeResource SystemControlPageTextBaseMediumBrush}" />
                <TextBlock Text="&#x2981;" Margin="8 0" />
                <TextBlock Text="{Binding Path=RetweetedStatus.CreationDate, Converter={StaticResource FormatDate}}" />
            </StackPanel>
        </Grid>
        <Grid Grid.Row="2">
            <TextBlock Text="{Binding RetweetedStatus.Text}" Padding="5" TextWrapping="WrapWholeWords" />
        </Grid>
        <Grid Grid.Row="3">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="2.5*" MaxWidth="100"/>
                <ColumnDefinition Width="2.5*"/>
                <ColumnDefinition Width="2.5*"/>
                <ColumnDefinition Width="2.5*"/>
            </Grid.ColumnDefinitions>
            <Grid Grid.Column="0">
                <Button x:Name="cmdComment" Content="&#xf075;" Style="{StaticResource MetaButtons}" />
            </Grid>
            <Grid Grid.Column="1">
                <Button x:Name="cmdRetweet" Content="&#xf079;" Style="{StaticResource MetaButtons}" />
            </Grid>
            <Grid Grid.Column="2">
                <Button x:Name="cmdLike" Content="&#xf004;" Style="{StaticResource MetaButtons}" />
            </Grid>
            <Grid Grid.Column="3">
                <Button x:Name="cmdMessage" Content="&#xf0e0;" Style="{StaticResource MetaButtons}" />
            </Grid>
        </Grid>
    </Grid>
</DataTemplate>

<local:TweetTemplateSelector x:Key="TweetTemplateSelector"
    TweetTemplate="{StaticResource TweetTemplate}"
    RetweetTemplate="{StaticResource RetweetTemplate}">
</local:TweetTemplateSelector>

2 个答案:

答案 0 :(得分:0)

通常,您需要为不同的消息类型创建匹配项Datatemplate。 UWP具有DataTemplateSelector类,可用于动态选择指定的Datatemplate。例如,

ListViewDataTemplateSelector.cs

public class ListViewDataTemplateSelector : DataTemplateSelector
{
    public DataTemplate MaleData { set; get; }
    public DataTemplate FemaleData { set; get; }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        if (item is Male)
        {
            return MaleData;
        }
        return FemaleData;
    }
}

用法

<Page.Resources>
    <DataTemplate x:Key="MaleData">
        <Grid>
           <Border>
               <Grid Margin="10,10,10,10">
                    <StackPanel>
                        <TextBlock Text="Name"></TextBlock>
                        <TextBlock Text="{Binding Path=Name}"></TextBlock>
                        <TextBlock Text="Height"></TextBlock>
                        <TextBlock Text="{Binding Path=Stature}"></TextBlock>
                    </StackPanel>
                </Grid>
           </Border>
        </Grid>
    </DataTemplate>
    <DataTemplate x:Key="FemaleData">
        <Grid>
            <Border>
                <Grid Margin="10,10,10,10">
                    <StackPanel>
                        <TextBlock Text="Name"></TextBlock>
                        <TextBlock Text="{Binding Path=Name}"></TextBlock>
                        <TextBlock Text="Age"></TextBlock>
                        <TextBlock Text="{Binding Path=Year}"></TextBlock>
                    </StackPanel>
                </Grid>
            </Border>
        </Grid>
    </DataTemplate>
    <local:ListViewDataTemplateSelector x:Key="Selector" FemaleData="{StaticResource FemaleData}"
                                        MaleData="{StaticResource MaleData}"></local:ListViewDataTemplateSelector>
</Page.Resources>
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <ListView ItemsSource="{x:Bind View.HumanWorld}"
              ItemTemplateSelector="{StaticResource Selector}"></ListView>
    <TextBlock Text="http://blog.csdn.net/lindexi_gd" VerticalAlignment="Bottom"></TextBlock>
</Grid>
  

那么有什么办法可以减少冗余代码呢?还是我坚持为每种可能的组合制作几乎重复的模板以容纳媒体并通过媒体转发了推文?

我知道您想要更少的冗余代码,但是编写的冗余代码越少,您需要的行为控制就越多。这将增加代码的复杂性。尽管为每种消息类型创建Datatemplates是多余的,但是代码很简单。

答案 1 :(得分:0)

  

不必为每种可能的组合复制相同的function integer(a,b) { if (a > 0 && b > 0 && a > b) { document.write("The larger number is " + a ); } else if (a > 0 && b > 0 && a < b) { document.write("The larger number is " + b); } else if (a === b && a > 0 && b > 0) { document.write("Both numbers are equal!") } else { document.write("Please add an integer!"); } } integer(-1,-1); ,有没有办法在不同的tweet类型之间重用主Tweet模板?

不。您不能将模板基于另一个模板。 DataTemplate必须始终定义为一个整体,即,您不能仅“覆盖”模板的一部分,而保留其余部分。 XAML不支持此功能。

  

还是我会为每种可能的组合制作一个几乎重复的模板,以容纳媒体并通过媒体转发了推文?

是的,恐怕是这样。您可以考虑使用Xaml​Reader类以编程方式创建模板,以便能够重复使用尽可能多的标记。