Windows Phone 8.1 Listview唯一的第一个和最后一个项目模板

时间:2015-03-06 16:01:47

标签: c# listview windows-phone windows-phone-8.1

去年我为Windows Phone 8制作了一个应用程序,其中包含一个LongListSelector,其中包含唯一的第一个和最后一个项目模板,如下所述:

LongListSelector different item template for first and last item

我最近将应用更新到了Windows Phone 8.1商店,这个功能破了。这是我的类(与帖子的唯一区别是,我使用的是ListView而不是Windows Phone 8.1 Store的LongListSelector,因为LongListSelector不是Windows Phone 8.1 Store框架的一部分):

public abstract class TemplateSelector : ContentControl
{
    public abstract DataTemplate SelectTemplate(object item, int index, int totalCount, DependencyObject container);

    protected override void OnContentChanged(object oldContent, object newContent)
    {
        base.OnContentChanged(oldContent, newContent);

        var parent = GetParentByType<ListView>(this);
        var index = (parent.ItemsSource as IList).IndexOf(newContent);
        var totalCount = (parent.ItemsSource as IList).Count;

        ContentTemplate = SelectTemplate(newContent, index, totalCount, this);
    }

    private static T GetParentByType<T>(DependencyObject element) where T : FrameworkElement
    {
        T result = null;
        DependencyObject parent = VisualTreeHelper.GetParent(element);

        while (parent != null)
        {
            result = parent as T;

            if (result != null)
            {
                return result;
            }

            parent = VisualTreeHelper.GetParent(parent);
        }

        return null;
    }
}

问题在于:

DependencyObject parent = VisualTreeHelper.GetParent(element);
由于某种原因,GetParentByType函数的

返回null。任何人都知道为什么或有替代解决方案?

下面是我的XAML代码(删除了几个xmlns)。 DataTrigger就在那里,因为有时候一个唯一的第一个项目模板就足够了(由ViewModel的LoadMore属性控制,这是一个bool)。

<controls:WP81Page
xmlns:core="using:Microsoft.Xaml.Interactions.Core"
xmlns:interactivity="using:Microsoft.Xaml.Interactivity"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">

<controls:WP81Page.Resources>
    <DataTemplate x:Key="first">
        <Grid HorizontalAlignment="Left" Width="Auto" Height="200">
            <Border BorderThickness="1" BorderBrush="Black" Visibility="{Binding NoLargeImage, Converter={StaticResource BoolToVisibilityConverter}}" >
                <Image Source="/Images/default-image.png" Stretch="UniformToFill" />
            </Border>
            <Border BorderThickness="1" BorderBrush="Black" Visibility="{Binding NoLargeImage, Converter={StaticResource BoolToVisibilityConverterReverse}}" >
                <Image Source="{Binding LargeImageUrl}" Stretch="UniformToFill" />
            </Border>
            <StackPanel VerticalAlignment="Bottom" Background="#7F000000" >
                <TextBlock Text="{Binding Header}" VerticalAlignment="Center" TextWrapping="Wrap" Foreground="White" FontWeight="Bold" Margin="15,0,15,15"/>
            </StackPanel>
        </Grid>
    </DataTemplate>
    <DataTemplate x:Key="default">
        <StackPanel Orientation="Horizontal" Margin="0,10,0,0" Height="105" Width="Auto">
            <Border BorderThickness="1" BorderBrush="Black" Margin="0,2" Visibility="{Binding NoSmallImage, Converter={StaticResource BoolToVisibilityConverter}}" >
                <Image Source="/Images/default-image.png" Width="130" Height="100" Stretch="UniformToFill" />
            </Border>
            <Border BorderThickness="1" BorderBrush="Black" Margin="0,2" Visibility="{Binding NoSmallImage, Converter={StaticResource BoolToVisibilityConverterReverse}}">
                <Image Source="{Binding SmallImageUrl}" Width="130" Height="100" Stretch="UniformToFill"/>
            </Border>
            <StackPanel Orientation="Vertical" Width="300" Margin="8,0,0,0">
                <TextBlock Text="{Binding Header}" TextWrapping="Wrap" FontWeight="Bold"  />
                <TextBlock Margin="0,3,0,0" Text="{Binding DisplayDate}" TextWrapping="Wrap" Foreground="#FFB9B9B9" FontSize="16" />
            </StackPanel>
        </StackPanel>
    </DataTemplate>
    <DataTemplate x:Key="last">
        <TextBlock Text="hent flere nyheder" FontSize="25" Margin="0,20" TextWrapping="Wrap" VerticalAlignment="Center" HorizontalAlignment="Center" Height="75"  />
    </DataTemplate>


    <DataTemplate x:Key="UniqueFirstTemplateSelector">
        <common:UniqueFirstTemplateSelector Content="{Binding}" First="{StaticResource first}" Default="{StaticResource default}" HorizontalAlignment="Stretch"/>
    </DataTemplate>
    <DataTemplate x:Key="UniqueFirstAndLastTemplateSelector">
        <common:UniqueFirstAndLastTemplateSelector Content="{Binding}" First="{StaticResource first}" Default="{StaticResource default}" Last="{StaticResource last}" HorizontalAlignment="Stretch"/>
    </DataTemplate>
</controls:WP81Page.Resources>

<controls:WP81Page.DataContext>
    <viewModels:NewsViewModel/>
</controls:WP81Page.DataContext>

<Grid x:Name="LayoutRoot" Style="{Binding Source={StaticResource Background}}">
    <Grid.RowDefinitions>
        <RowDefinition Height="Auto"/>
        <RowDefinition Height="*"/>
    </Grid.RowDefinitions>
    <ProgressBar Grid.Row="0" VerticalAlignment="Top" IsIndeterminate="True" Background="Transparent" Foreground="White" Visibility="{Binding IsLoading, Converter={StaticResource BoolToVisibilityConverter}}" />

    <StackPanel Grid.Row="0" Margin="12,17,0,28">
        <TextBlock Text="NYHEDER" FontSize="35" FontWeight="Bold" Style="{StaticResource PhoneTextNormalStyle}"/>
    </StackPanel>

    <Grid x:Name="ContentPanel" Grid.Row="1">
        <controls:WP81ListView x:Name="listSelector" Margin="22,0" Grid.Row="2" ItemsSource="{Binding News}" Command="{Binding NewsEntrySelectedCommand}" >
            <interactivity:Interaction.Behaviors>
                <core:DataTriggerBehavior Binding="{Binding LoadMore}" Value="True">
                    <core:ChangePropertyAction TargetObject="{Binding ElementName=listSelector}"
                        Value="{StaticResource UniqueFirstAndLastTemplateSelector}"
                        PropertyName="ItemTemplate" />
                </core:DataTriggerBehavior>
                <core:DataTriggerBehavior Binding="{Binding LoadMore}" Value="False">
                    <core:ChangePropertyAction TargetObject="{Binding ElementName=listSelector}"
                        Value="{StaticResource UniqueFirstTemplateSelector}"
                        PropertyName="ItemTemplate" />
                </core:DataTriggerBehavior>
            </interactivity:Interaction.Behaviors>
        </controls:WP81ListView>
    </Grid>
</Grid>

</controls:WP81Page>

提前谢谢。

修改

好吧,所以我想要的不是第一个和最后一个项目始终是唯一的。我正在制作新闻Feed,其中最后一项只有在有更多新闻条目要加载时才会是唯一的(当点击最后一项时,会有更多新闻条目添加到ListView)。但是,如果到达新闻条目的结尾,则最后一项不能是唯一的(因此与交互性组合)。

1 个答案:

答案 0 :(得分:3)

ListView有一个名为ItemTemplateSelector的属性,它接受基于DataTemplateSelector的对象。所以你需要改变一些事情才能让它发挥作用。

首先,模板选择器的定义。它需要基于DataTemplateSelector和覆盖方法SelectTemplateCore。它需要一个ListViewItem对象。此时,您可以使用VisualTree获取ListView并根据索引选择DataTemplate。

public class MyTemplateSelector : DataTemplateSelector
{
    public DataTemplate First { get; set; }
    public DataTemplate Default { get; set; }
    public DataTemplate Last { get; set; }

    protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
    {
        var listViewItem = container as ListViewItem;
        var listView = GetParentByType<ListView>(listViewItem); 

        var index = (listView.ItemsSource as IList).IndexOf(item);
        var totalCount = (listView.ItemsSource as IList).Count;

        if (index == 0)
            return First;
        else if (index == totalCount - 1)
            return Last;
        else
            return Default;
    }

    private T GetParentByType<T>(DependencyObject element) where T : FrameworkElement
    {
        T result = null;
        DependencyObject parent = VisualTreeHelper.GetParent(element);

        while (parent != null)
        {
            result = parent as T;

            if (result != null)
            {
                return result;
            }

            parent = VisualTreeHelper.GetParent(parent);
        }

        return null;
    }
}

然后,您需要在静态资源中创建它的实例

<local:MyTemplateSelector x:Key="SelectingTemplate" 
                          First="{StaticResource first}"
                          Default="{StaticResource default}"
                          Last="{StaticResource last}" />

使用First,Default和Last DataTemplates,就像之前一样。

最后一步是将它应用到您正在使用的ListView。

<ListView ItemsSource="{Binding SomeItemsSource}" 
          ItemTemplateSelector="{StaticResource SelectingTemplate}" />

那就是它!