You can customize grouping by a Comparer in GroupDescriptor and GroupHeader using the GroupHeaderTemplate with converter.
Here, the GroupHeader is customized as ListViewItem using the converter in GroupHeaderTemplate.
<syncfusion:SfListView x:Name="listView" GroupHeaderSize="300"
AutoFitMode="DynamicHeight"
SelectionMode="Single"
ItemsSource="{Binding MemberDetails}">
<syncfusion:SfListView.GroupHeaderTemplate>
<DataTemplate>
<StackLayout BackgroundColor="LightGray">
<Image x:Name="ScrumMasterImage" Source="{Binding
Converter={StaticResource Converter},
ConverterParameter=ScrumMasterImage}"
VerticalOptions="Center"
HeightRequest="80" WidthRequest="80"
HorizontalOptions="CenterAndExpand"
Margin="10" />
<Label x:Name="ScrumMasterRole" Text="{Binding
Converter={StaticResource Converter},
ConverterParameter=ScrumMasterRole}"
FontSize="20"
HorizontalOptions="CenterAndExpand"
VerticalOptions="Center"/>
<Label x:Name="ScrumMasterName" Text="{Binding
Converter={StaticResource Converter},
ConverterParameter=ScrumMasterName}"
FontSize="18"
Padding="0,0,0,10"
HorizontalOptions="CenterAndExpand"
VerticalOptions="Center"/>
</StackLayout>
</DataTemplate>
</syncfusion:SfListView.GroupHeaderTemplate>
</syncfusion:SfListView>
Converter, which designs the group header.
class Converter : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
if (value == null)
return null;
string id = parameter as string;
var groupResult = value as GroupResult;
foreach (var item in groupResult.Items)
{
if(id == "ScrumMasterImage")
{
return (item as TeamInfo).MemberImage;
}
else if(id == "ScrumMasterRole")
{
return (item as TeamInfo).Role;
}
else if (id == "ScrumMasterName")
{
return (item as TeamInfo).MemberName;
}
}
return null;
}
public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
The GridLayout defined in the LayoutManager with column count as 2 using the SpanCount property.
<syncfusion:SfListView x:Name="listView">
<syncfusion:SfListView.LayoutManager>
<syncfusion:GridLayout SpanCount="2"/>
</syncfusion:SfListView.LayoutManager>
</syncfusion:SfListView>
The GroupDescriptor defined with comparer to sort the specific group always to be at the top of the rows.
public class Behavior : Behavior<SfListView>
{
protected override void OnAttachedTo(SfListView bindable)
{
bindable.DataSource.GroupDescriptors.Add(new GroupDescriptor()
{
PropertyName = "IsScrumMaster",
Comparer = new GroupComparer()
});
base.OnAttachedTo(bindable);
}
}
public class GroupComparer : IComparer<GroupResult>
{
public int Compare(GroupResult x, GroupResult y)
{
if (x.Count > y.Count)
{
return 1;
}
else if (x.Count < y.Count)
{
return -1;
}
return 0;
}
}
QueryItemSize to reset the Height of the groups that are not needed to show in the view to zero.
public class Behavior : Behavior<SfListView>
{
protected override void OnAttachedTo(SfListView bindable)
{
bindable.QueryItemSize += Bindable_QueryItemSize;
}
private void Bindable_QueryItemSize(object sender, QueryItemSizeEventArgs e)
{
var bindingContext = (sender as SfListView).BindingContext as TeamInfoRepository;
var collection = bindingContext.MemberDetails;
var type = e.ItemType;
if (type == ItemType.GroupHeader && (bool)(e.ItemData as GroupResult).Key) ;
else if (type == ItemType.GroupHeader
&& !(bool)(e.ItemData as GroupResult).Key)
{
e.ItemSize = 0;
e.Handled = true;
}
if (type == ItemType.Record)
{
var isManager = (e.ItemData as TeamInfo).IsScrumMaster;
if (isManager)
{
e.ItemSize = 0;
e.Handled = true;
}
}
}
protected override void OnDetachingFrom(SfListView bindable)
{
bindable.QueryItemSize -= Bindable_QueryItemSize;
base.OnDetachingFrom(bindable);
}
}
Output