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

本文关键字:一项 Phone 最后 Windows Listview 唯一 | 更新日期: 2024-10-18 23:26:25

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

LongListSelector第一个和最后一个项目的不同项目模板

我最近将该应用程序更新到Windows Phone 8.1应用商店,但此功能已损坏。这是我的课程(与帖子的唯一区别是,我在Windows Phone 8.1 Store中使用ListView而不是LongListSelector,因为LongListSelecter不是Windows Phone 8.1商店框架的一部分):

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代码(去掉了一些xmln)。DataTrigger之所以存在,是因为有时一个唯一的第一项模板就足够了(由ViewModel的LoadMore属性控制,该属性是布尔)。

<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>

提前谢谢。

编辑

好吧,所以我想要的不是第一件和最后一件一直都是独一无二的。我正在制作一个新闻提要,其中只有当有更多的新闻条目要加载时,最后一个条目才是唯一的(当单击最后一个项目时,会向ListView中添加更多的新闻条目的)。但是,如果到达了新闻条目的末尾,则最后一个条目必须不是唯一的(因此与交互性相结合)。

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

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}" />

就这样!