如何使用 ListViewRenderer 在 Xamarin UWP 中使用 ListView 的 GroupHeader 模板

Posted

技术标签:

【中文标题】如何使用 ListViewRenderer 在 Xamarin UWP 中使用 ListView 的 GroupHeader 模板【英文标题】:How to use GroupHeader template of a ListView in Xamarin UWP using ListViewRenderer 【发布时间】:2017-02-06 03:33:24 【问题描述】:

我在App.xaml 中定义了以下HeaderTemplate

<DataTemplate x:Key="ListViewGroupHeaderTemplate">
    <TextBlock Foreground="Black" Text="Something" />
</DataTemplate>

我在我的ListViewRenderer 中使用这种方式:

listView.ItemTemplate = App.Current.Resources["ListViewItemTemplate"] as Windows.UI.Xaml.DataTemplate;
var gs = new GroupStyle();
gs.HeaderTemplate = App.Current.Resources["ListViewGroupHeaderTemplate"] as Windows.UI.Xaml.DataTemplate;
listView.GroupStyle.Add(gs);

ListView的来源是CollectionViewSource

CollectionViewSource cvs = new CollectionViewSource();
cvs.IsSourceGrouped = true;

cvs.Source = ((SourceListView)Element).Items;
if (listView.ItemsSource == null)
  listView.ItemsSource = cvs.View;

ItemTemplate 运行良好。

这就是我的ListView 的样子(白色部分是组标题):

我应该设置什么来使标题起作用?

更新

我根据答案修改了我的来源(应用分组到一个简单的列表):

    CollectionViewSource cvs = new CollectionViewSource();
    cvs.IsSourceGrouped = true;
    var items = ((MyListView)Element).Items;
    var itemsAsOC = items as ObservableCollection<GroupListItem>;
    List<ListItem> list = new List<ListItem>();
    foreach (var item in itemsAsOC)
    
      list.AddRange(item);
    
    var group = from item in list group item by item.Value into grp orderby grp.Key select grp;                
    cvs.Source = group;

标头没有任何变化,所以我猜数据源是正确的,但是模板处理中存在一些严重的 Xamarin UWP 错误:

更新 2:

我在没有 Xamarin 渲染器的情况下测试了它,它显示了标题项。

但是,当我使用 Xamarin 渲染器时,标题消失了

您可以download 并对其进行实际测试。

【问题讨论】:

【参考方案1】:

基本上我在您的代码中找不到任何明显的问题,这是我将GroupHeader 模板添加到ListView 的方法。

在 App.xaml 中:

<Application.Resources>
    <DataTemplate x:Key="ListViewGroupHeaderTemplate">
        <TextBlock Foreground="Red" Text="Binding Key" />
    </DataTemplate>
    <DataTemplate x:Key="ListViewTemplate">
        <TextBlock Foreground="Black" Text="Binding DateTimeProperty" />
    </DataTemplate>
</Application.Resources>

这是我的物品类别和我的SourceListView

public class ListItem

    public DateTime DateTimeProperty  get; set; 


public class SourceListView

    public SourceListView()
    
        Element = from x in Collection group x by x.DateTimeProperty.Year into grp orderby grp.Key select grp;
    

    public IList<ListItem> Collection  get; set;  = new List<ListItem>()
    
        new ListItem() DateTimeProperty = DateTime.Parse("2011-08-01") ,
        new ListItem() DateTimeProperty = DateTime.Parse("2011-08-21") ,
        new ListItem() DateTimeProperty = DateTime.Parse("2012-04-03") ,
        new ListItem() DateTimeProperty = DateTime.Parse("2012-04-01") ,
        new ListItem() DateTimeProperty = DateTime.Parse("2013-05-15") ,
        new ListItem() DateTimeProperty = DateTime.Parse("2013-05-06") ,
        new ListItem() DateTimeProperty = DateTime.Parse("2013-05-01") ,
        new ListItem() DateTimeProperty = DateTime.Parse("2013-06-01") ,
        new ListItem() DateTimeProperty = DateTime.Parse("2013-06-09") ,
        new ListItem() DateTimeProperty = DateTime.Parse("2014-10-02") ,
        new ListItem() DateTimeProperty = DateTime.Parse("2014-10-11") ,
        new ListItem() DateTimeProperty = DateTime.Parse("2015-12-03") ,
        new ListItem() DateTimeProperty = DateTime.Parse("2016-07-01") ,
        new ListItem() DateTimeProperty = DateTime.Parse("2016-07-06") ,
    ;

    public IEnumerable<object> Element  get; 

这里是这个分组ListView的实现代码:

ListView listView = new ListView();
listView.ItemTemplate = App.Current.Resources["ListViewTemplate"] as Windows.UI.Xaml.DataTemplate;
var gs = new GroupStyle();
gs.HeaderTemplate = App.Current.Resources["ListViewGroupHeaderTemplate"] as Windows.UI.Xaml.DataTemplate;
listView.GroupStyle.Add(gs);

CollectionViewSource cvs = new CollectionViewSource();
cvs.IsSourceGrouped = true;
cvs.Source = new SourceListView().Element;
if (listView.ItemsSource == null)
    listView.ItemsSource = cvs.View;
rootGrid.Children.Add(listView);

这是渲染图:

【讨论】:

如果我添加以下代码:˛listView.HeaderTemplate = App.Current.Resources["ListViewGroupHeaderTemplate"] as Windows.UI.Xaml.DataTemplate;,然后出现主标题,所以我猜,组标题设置错误。我应该在我的 CollectionViewSource 中设置键值吗? @Nestor,如果你设置了listView.HeaderTemplate = App.Current.Resources["ListViewGroupHeaderTemplate"] as Windows.UI.Xaml.DataTemplate;,那么这个header就是这个ListView的主header,你的group应该是通过item in order来构建失败的,但是每个group的header应该是缺失的。 .."Should I set a key value in my CollectionViewSource", key value是分组标题,它使用LinQ进行分组,分组时它们是键值对,所以我在@中使用Key进行绑定987654333@,在CollectionViewSource,你只需要添加这个模板。 我修改了我的模板,fix title 被替换为Binding Key,但没有任何改变。另外,我想修复标题应该是可见的,因为它在绑定时不依赖任何东西。我将GroupStyle 添加到我的XAML,但标题仍然是一个白色矩形。很奇怪,妨碍了我的工作。 我在最初的问题中添加了一些信息。我没有足够强调它是我使用的 Xamarin ListViewRenderer。【参考方案2】:

好的,经过一天半的努力解决这个问题后,我终于找到了解决方案。如果有一天有人遇到和我一样的问题,我会在这里发布。其实这是一个很奇怪的问题,我不知道这是一个错误,未实现的功能还是什么......

解决办法:

在您的 UWP 自定义渲染器中,您需要这样做:

 protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.ListView> e)
    
        base.OnElementChanged(e);

        if (e.NewElement != null)
        
            e.NewElement.GroupHeaderTemplate = new Xamarin.Forms.DataTemplate(() =>
            
                var label = new Label();

                label.SetBinding(Label.TextProperty, "Country");

                return new ViewCell  View = label ;
            );
        
    

其中“国家/地区”是代表您的组/标题的类中的属性名称。

【讨论】:

以上是关于如何使用 ListViewRenderer 在 Xamarin UWP 中使用 ListView 的 GroupHeader 模板的主要内容,如果未能解决你的问题,请参考以下文章

如何在 Python 3.x 和 Python 2.x 中使用 pip

如何在 Qt 中使用 x()、y() 函数

如何使用 Python 计算多项式 255×x*5 +127×x*3-63/x在 x =5时的值?

如何使用 FluentAssertions 4.x 版断言异常?

如何使用coderunner在OS X

如何在节点中使用 x.509 证书验证 JWT 令牌?