C# Forms-更新ItemSource时ViewCell内的图像闪烁

C# Forms-更新ItemSource时ViewCell内的图像闪烁,c#,listview,xamarin,xamarin.forms,C#,Listview,Xamarin,Xamarin.forms,我正在Xamarin.Forms项目中开发一个手风琴列表视图。这意味着您可以单击ListView中的类别标题,这将展开或折叠其下的子项 每个类别标题中有两个图像和一个标题,因此我使用的是ViewCell。问题是,当点击一个类别并显示子类别时,类别标题ViewCell上的图像会闪烁 我有两个可观察的收藏,我用它们来完成手风琴的功能。一个包含每个父项(MenuItemGroup)和子项(MenuItem)项,另一个仅包含应显示的MenuItem)。每次点击标题时,都会触发一个事件,该事件获取类别的选

我正在Xamarin.Forms项目中开发一个手风琴列表视图。这意味着您可以单击ListView中的类别标题,这将展开或折叠其下的子项

每个类别标题中有两个图像和一个标题,因此我使用的是ViewCell。问题是,当点击一个类别并显示子类别时,类别标题ViewCell上的图像会闪烁

我有两个可观察的收藏,我用它们来完成手风琴的功能。一个包含每个父项(
MenuItemGroup
)和子项(
MenuItem
)项,另一个仅包含应显示的
MenuItem
)。每次点击标题时,都会触发一个事件,该事件获取类别的选定索引并切换其
展开的
属性(显示或隐藏其子项)。然后调用
UpdateListContent()
方法来刷新ListView项目源:

    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;
    }
private observedcollection\u所有组;
私有可观测集合_expandedGroups;
私有void OnHeaderTapped(对象发送方,事件参数e)
{
var selectedIndex=\u expandedGroups.IndexOf(
((MenuItemGroup)((StackLayout)sender.Parent.BindingContext));
_所有组[selectedIndex]。展开=!\u所有组[selectedIndex]。展开;
UpdateListContent();
}
私有void UpdateListContent()
{
_expandedGroups=新的ObservableCollection();
foreach(所有组中的var组)
{
var newGroup=new MenuItemGroup(group.Title,group.CategoryIcon,group.Expanded);
如果(group.Count==0)
{
newGroup.Expanded=null;
}
if(group.Expanded==true)
{
foreach(组中的var menuItem)
{
添加(菜单项);
}
}
_expandedGroups.Add(newGroup);
}
_menuItemListView.ItemsSource=\u expandedGroups;
}
以下是DateTemplate和图像绑定:

        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
        };
var menuItemGroupTemplate=新数据模板(()=>
{
var groupImage=新图像();
SetBinding(Image.SourceProperty,i=>i.CategoryIcon);
var titleLabel=新标签
{
TextColor=Color.White,
VerticalTextAlignment=TextAlignment.Center,
垂直选项=布局选项。中心,
FontSize=Device.GetNamedSize(NamedSize.Medium,typeof(Label))
};
titleLabel.SetBinding(Label.TextProperty,t=>t.Title);
var stateIconImage=新图像
{
水平选项=LayoutOptions.EndAndExpand
};
SetBinding(Image.SourceProperty,i=>i.IconState);
var menuItemGroupStackLayout=新建StackLayout
{
BackgroundColor=Color.FromHex(“40474d”),
HorizontalOptions=LayoutOptions.FillAndExpand,
VerticalOptions=LayoutOptions.FillAndExpand,
方向=堆叠方向。水平,
填充=新厚度(10,0,20,0),
Children={groupImage,titleLabel,stateIconImage}
};
var tapGestureRecognizer=新的tapGestureRecognizer();
TapGestureRecognitor.Tapped+=OnHeaderTapped;
tapGestureRecognizer.CommandParameter=menuItemGroupStackLayout.BindingContext;
menuItemGroupStackLayout.GestureRecognizers.Add(tapGestureRecognizer);
var menuItemGroupViewCell=新的ViewCell
{
View=menuItemGroupStackLayout,
高度=63.0
};
返回menuItemGroupViewCell;
});
_menuItemListView=新建ListView
{
行高=55,
IsGroupingEnabled=true,
ItemTemplate=menuItemTemplate,
GroupHeaderTemplate=menuItemGroupTemplate,
SeparatorColor=Color.FromHex(“40474d”),
HasRows=true
};
更新ListView ItemSource时,组图标和状态图标都会闪烁。有人能提供一些关于如何解决这个问题的见解吗?谢谢


如果您认为有帮助,我可以发布
MenuItemGroup
MenuItem
类。

我在尝试用图像更新列表视图时遇到了类似的问题。我在Android中看到图像闪烁。这通常是因为加载图像的延迟

尝试固定图像的高度和宽度。如果这不起作用,则在更新列表内容时,只更新所需的图像和文本值,以便不需要再次加载所有图像

如果您真的需要,我可以提供一个示例代码,因为您只需要了解一些情况

下面是您可以做的: 用_expandedGroups绑定Listview.Itemsource,这样就不必每次展开/折叠时都设置ItemsSource属性。这将刷新您的列表,从而刷新您的图像

private ObservableCollection<MenuItemGroup> _expandedGroups;
public ObservableCollection<MenuItemGroup> ExpandedGroups
{
 get
 {
  return _expandedGroups;
 }
 set
 {
  if(value!=null) _expandedGroups = value;
  OnPropertyChanged("ExpandedGroups");
 }
}

干杯。

面临同样的问题。。令人惊讶的是,在我将通知控件需要更新的代码放入设备后,闪烁完全消失。BeginInvokeOnMainThread。

感谢您的回答。您能否提供任何示例代码来演示如何在不更新
groupImage
的情况下更新listview。
groupImage
在每个菜单项的组标题中都是不同的,因此绑定SouceProperty是我知道如何设置每个图像的唯一方法我已经给出了可以做什么的要点。根据需要进行修改,并检查这是否可以防止闪烁。在我实现代码以仅更新将要更改的部分后,只剩下一小部分闪烁。一旦我添加了一个图像宽度和高度的小闪烁disa
UpdateListContent(_allGroups[SelectedIndex], SelectedIndex);
private void UpdateListContent(MenuItemGroup group, int index)
{
 if(group.Expanded)
 {
  foreach (var menuItem in group)
   {
     ExpandedGroup.Insert(index++, menuItem);
   }
 }
 else
 {
  foreach (var menuItem in group)
   {
     ExpandedGroup.Remove(menuItem); //Can also use ExpandedGroup.RemoveAt(index++);   
   }
  }
}