I am working on an Accordion ListView in a Xamarin.Forms project. This means that you can click on Category Headings in a ListView, which will expand or collapse the children beneath it.
There are two images and a title in each Category Heading so I am using a ViewCell. The issue is that when a Category is tapped and the children are shown, the images on the Category Heading ViewCell flash.
I have two observable collections that I am using to accomplish the Accordion Functionality. One that contains every parent (MenuItemGroup) and child (MenuItem) item, and one that only includes the MenuItem's that should be shown. Every time a header is tapped, an event fires that gets the selected Index of the Category and toggles it's Expanded property (showing or hiding it's children). Then the UpdateListContent() method is called to refresh the ListView ItemSource:
private ObservableCollection<MenuItemGroup> _allGroups;
private ObservableCollection<MenuItemGroup> _expandedGroups;
private void OnHeaderTapped(object sender, EventArgs e)
{
var selectedIndex = _expandedGroups.IndexOf(
((MenuItemGroup)((StackLayout)sender).Parent.BindingContext));
_allGroups[selectedIndex].Expanded = !_allGroups[selectedIndex].Expanded;
UpdateListContent();
}
private void UpdateListContent()
{
_expandedGroups = new ObservableCollection<MenuItemGroup>();
foreach (var group in _allGroups)
{
var newGroup = new MenuItemGroup(group.Title, group.CategoryIcon, group.Expanded);
if (group.Count == 0)
{
newGroup.Expanded = null;
}
if (group.Expanded == true)
{
foreach (var menuItem in group)
{
newGroup.Add(menuItem);
}
}
_expandedGroups.Add(newGroup);
}
_menuItemListView.ItemsSource = _expandedGroups;
}
Here is the DateTemplate and Image Binding:
var menuItemGroupTemplate = new DataTemplate(() =>
{
var groupImage = new Image();
groupImage.SetBinding<MenuItemGroup>(Image.SourceProperty, i => i.CategoryIcon);
var titleLabel = new Label
{
TextColor = Color.White,
VerticalTextAlignment = TextAlignment.Center,
VerticalOptions = LayoutOptions.Center,
FontSize = Device.GetNamedSize(NamedSize.Medium, typeof(Label))
};
titleLabel.SetBinding<MenuItemGroup>(Label.TextProperty, t => t.Title);
var stateIconImage = new Image
{
HorizontalOptions = LayoutOptions.EndAndExpand
};
stateIconImage.SetBinding<MenuItemGroup>(Image.SourceProperty, i => i.IconState);
var menuItemGroupStackLayout = new StackLayout
{
BackgroundColor = Color.FromHex("40474d"),
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
Orientation = StackOrientation.Horizontal,
Padding = new Thickness(10 ,0, 20, 0),
Children = { groupImage, titleLabel, stateIconImage }
};
var tapGestureRecognizer = new TapGestureRecognizer();
tapGestureRecognizer.Tapped += OnHeaderTapped;
tapGestureRecognizer.CommandParameter = menuItemGroupStackLayout.BindingContext;
menuItemGroupStackLayout.GestureRecognizers.Add(tapGestureRecognizer);
var menuItemGroupViewCell = new ViewCell
{
View = menuItemGroupStackLayout,
Height = 63.0
};
return menuItemGroupViewCell;
});
_menuItemListView = new ListView
{
RowHeight = 55,
IsGroupingEnabled = true,
ItemTemplate = menuItemTemplate,
GroupHeaderTemplate = menuItemGroupTemplate,
SeparatorColor = Color.FromHex("40474d"),
HasUnevenRows = true
};
Both the groupIcon and stateIcon images flash when the ListView ItemSource is updated. Can anyone offer any insight into how to fix this issue? Thanks!
I can post the MenuItemGroup and MenuItem classes if you think it would be helpful.