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

MVVM模式下如何将SciChartLegend迁移至独立UserControl

解决方案:MVVM模式下跨UserControl分离SciChartSurface与SciChartLegend

问题核心分析

你遇到的问题本质是:在MVVM架构下,LegendModifier需要自动生成图例数据并同步到ViewModel的LegendData属性,再让独立UserControl中的SciChartLegend绑定该属性。之前的错误在于手动初始化了空的ChartDataObject,且未正确配置绑定方向,同时需确保两个UserControl共享同一ViewModel实例。


步骤1:修正ViewModel中的LegendData属性

ViewModel不需要手动初始化ChartDataObject,而是让LegendModifier自动生成并赋值给该属性。修改代码如下:

private ObservableCollection<IRenderableSeriesViewModel> _renderableSeries;
public ObservableCollection<IRenderableSeriesViewModel> RenderableSeries
{
    get { return _renderableSeries; }
    set
    {
        SetProperty(ref _renderableSeries, value, nameof(RenderableSeries));
    }
}

private ObservableCollection<IAnnotationViewModel> _annotations;
public ObservableCollection<IAnnotationViewModel> Annotations
{
    get { return _annotations; }
    set
    {
        SetProperty(ref _annotations, value, nameof(Annotations));
    }
}

// 仅声明属性,不手动初始化空对象
private ChartDataObject _legendData;
public ChartDataObject LegendData
{
    get { return _legendData; }
    set
    {
        SetProperty(ref _legendData, value, nameof(LegendData));
    }
}

private void InitCharts()
{
    _renderableSeries = new ObservableCollection<IRenderableSeriesViewModel>();
    _annotations = new ObservableCollection<IAnnotationViewModel>();
    // 移除这行:_legendData = new ChartDataObject();

    _lineDataDiameter1 = InitChart(new InitChartRequest() { ChartName = CHART_NAME_DIAMETER_1, LineColor = Colors.OrangeRed, ChartStyle = CHART_LINE_STYLE });
    _lineDataDiameter2 = InitChart(new InitChartRequest() { ChartName = CHART_NAME_DIAMETER_2, LineColor = Colors.BlueViolet, ChartStyle = CHART_LINE_STYLE });
    _lineDataCovering1 = InitChart(new InitChartRequest() { ChartName = CHART_NAME_COVERING_1, LineColor = Colors.LimeGreen, ChartStyle = CHART_LINE_STYLE });
    _lineDataCovering2 = InitChart(new InitChartRequest() { ChartName = CHART_NAME_COVERING_2, LineColor = Colors.DeepSkyBlue, ChartStyle = CHART_LINE_STYLE });
    _lineDataCovering3 = InitChart(new InitChartRequest() { ChartName = CHART_NAME_COVERING_3, LineColor = Colors.White, ChartStyle = CHART_LINE_STYLE });
}

private XyDataSeries<double, double> InitChart(InitChartRequest request)
{
    XyDataSeries<double, double> lineData = new()
    {
        SeriesName = request.ChartName,
    };

    RenderableSeries.Add(new LineRenderableSeriesViewModel()
    {
        Stroke = request.LineColor,
        DataSeries = lineData,
        StyleKey = request.ChartStyle,
    });

    return lineData;
}

步骤2:配置SciChartSurface所在UserControl的LegendModifier

修改LegendModifier的绑定方向为OneWayToSource,让Modifier将自动生成的图例数据推送给ViewModel的LegendData:

<Border Grid.Row="1" Grid.Column="0" Margin="5" Padding="5" BorderBrush="Black" BorderThickness="1,1,1,1" CornerRadius="5">
    <Grid>
        <s:SciChartSurface ChartTitle="{localVM:Localization MainChartSciChartSurface}" RenderableSeries="{s:SeriesBinding RenderableSeries}" Annotations="{s:AnnotationsBinding Annotations}">
            <s:SciChartSurface.XAxis>
                <s:NumericAxis AxisTitle="{localVM:Localization XNumericAxis}" VisibleRange="{Binding VisibleRangeXAxis, Mode=TwoWay}" />
            </s:SciChartSurface.XAxis>
            <s:SciChartSurface.YAxis>
                <s:NumericAxis AxisTitle="{localVM:Localization YNumericAxis}" VisibleRange="{Binding VisibleRangeYAxis, Mode=TwoWay}"
                               AutoRange="{Binding IsStaticYAxis, Converter={StaticResource StaticAxisToSciChartAutoRangeConverter}}" GrowBy="0.1,0.1" />
            </s:SciChartSurface.YAxis>
            <s:SciChartSurface.ChartModifier>
                <s:ModifierGroup>
                    <s:SeriesValueModifier />
                    <s:CursorModifier IsEnabled="{Binding IsShowValuesCursor}" />
                    <!-- 修改绑定方向为OneWayToSource,让Modifier生成的数据同步到ViewModel -->
                    <s:LegendModifier x:Name="SciChartLegendModifier" 
                                      LegendData="{Binding LegendData, Mode=OneWayToSource}" 
                                      GetLegendDataFor="AllSeries" 
                                      ShowLegend="False" />
                </s:ModifierGroup>
            </s:SciChartSurface.ChartModifier>
        </s:SciChartSurface>
    </Grid>
</Border>

步骤3:确保独立UserControl的SciChartLegend绑定正确

独立UserControl中的SciChartLegend直接绑定ViewModel的LegendData即可,同时必须保证该UserControl的DataContext与SciChartSurface所在UserControl的DataContext是同一个ViewModel实例(可通过父容器继承、依赖注入等方式实现):

<Border DockPanel.Dock="Top" Margin="5" Padding="5" BorderBrush="Black" BorderThickness="1,1,1,1" CornerRadius="5">
    <StackPanel>
        <s:SciChartLegend x:Name="SciChartLegendControl"
                          s:ThemeManager.Theme="Chrome"
                          Margin="5,5"
                          ScrollViewer.HorizontalScrollBarVisibility="Auto"
                          ScrollViewer.VerticalScrollBarVisibility="Auto"
                          LegendData="{Binding LegendData}"
                          ShowVisibilityCheckboxes="True" />
    </StackPanel>
</Border>

关键注意事项

  1. 共享ViewModel实例:两个UserControl必须绑定同一个ViewModel对象,否则LegendData无法跨控件同步。
  2. 依赖SciChart的自动生成:无需手动向LegendData添加数据,LegendModifier会自动根据RenderableSeriesViewModel生成对应的图例条目(已通过SeriesName设置显示名称)。
  3. 绑定方向正确性:LegendModifier的LegendData绑定需设为OneWayToSource,确保生成的数据推送到ViewModel;SciChartLegend的绑定保持默认OneWay即可。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.01 18:40:55