You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Xamarin.Forms中CollectionView内嵌Expander的OxyPlot不显示问题求解

问题根因

该问题的核心原因是Xamarin Community Toolkit的Expander控件默认采用懒加载逻辑,收起状态下不会对内部内容进行测量和渲染,OxyPlot的PlotView在初始化时父容器处于不可见状态,因此不会触发绘图逻辑,导致展开后空白。


可行解决方案

方案1:局部刷新PlotView(最低改动,推荐)

不要在Expander的点击事件中重新加载整个CollectionView数据源,仅触发当前点击条目内PlotView的重绘即可,完全不会影响Expander的展开状态。

代码示例:

首先给XAML中的PlotView添加名称标识:

<oxy:PlotView x:Name="KidChart" HeightRequest="200" WidthRequest="200" Model="{Binding chart}" />

然后修改Expander的点击事件逻辑:

private void Expander_Tapped(object sender, EventArgs e)
{
    var expander = sender as Expander;
    if (expander == null || !expander.IsExpanded) return;
    // 查找当前Expander内的PlotView
    var plotView = expander.FindByName<PlotView>("KidChart");
    if (plotView?.Model != null)
    {
        // 强制重绘图表
        plotView.Model.InvalidatePlot(true);
        plotView.InvalidateMeasure();
    }
}

方案2:预渲染Expander内容

给ReportsClass添加IsExpanded属性并实现INotifyPropertyChanged接口,和Expander的IsExpanded属性双向绑定,初始化时短暂设置为展开状态触发内容渲染后再收起,后续展开就能直接显示图表。

代码示例:

修改ReportsClass定义:

public class ReportsClass : INotifyPropertyChanged
{
    private bool _isExpanded;
    public bool IsExpanded
    {
        get => _isExpanded;
        set { _isExpanded = value; OnPropertyChanged(); }
    }

    public PlotModel chart { get; set; }
    // 其他原有属性省略

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

绑定Expander的IsExpanded属性:

<xct:Expander IsExpanded="{Binding IsExpanded}">

初始化数据源时添加预渲染逻辑:

// 先把所有条目设为展开状态触发渲染
foreach (var item in newKidList)
{
    item.IsExpanded = true;
}
Kids.ItemsSource = newKidList;

// 100ms后自动收起所有条目
Device.StartTimer(TimeSpan.FromMilliseconds(100), () =>
{
    foreach (var item in newKidList)
    {
        item.IsExpanded = false;
    }
    return false;
});

方案3:替换控件规避问题

如果不想针对Expander做适配,可以选择替换相关控件彻底规避该类渲染问题:

  • 替换Expander:自定义折叠控件,用StackLayout的IsVisible属性或高度动画实现展开/收起效果,内部内容始终处于可视树中,OxyPlot初始化时就能正常渲染。
  • 替换CollectionView:如果条目数量不多(少于50条),可以直接用BindableLayout绑定普通StackLayout,完全规避CollectionView虚拟化带来的各类渲染异常问题,示例:
<ScrollView>
    <StackLayout x:Name="KidsContainer">
        <BindableLayout.ItemTemplate>
            <DataTemplate>
                <!-- 原有Expander和内部内容直接放在这里即可 -->
            </DataTemplate>
        </BindableLayout.ItemTemplate>
    </StackLayout>
</ScrollView>

后台赋值逻辑直接给BindableLayout.SetItemsSource(KidsContainer, newKidList)即可。


内容的提问来源于stack exchange,提问作者user979331

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.25 13:15:03