为什么我的2个Livecharts笛卡尔实例无效?

问题描述

我当前的代码有问题。

基本上,我需要在我的应用程序的一个网格中显示2个图,但它似乎无法正常工作。 问题在于将显示一张图,而第二张图将不会绘制。

下面是所使用的代码

XAML:

                   <Grid>
                        <lvc:CartesianChart x:Name="cartchartdb" Series="{Binding SeriesCollection}" LegendLocation="Right" Margin="10,249,578.4,218.2" >
                            <lvc:CartesianChart.AxisY>
                                <lvc:Axis Title="Average Gap (Meter)" LabelFormatter="{Binding YFormatter}"></lvc:Axis>
                            </lvc:CartesianChart.AxisY>
                            <lvc:CartesianChart.AxisX>
                                <lvc:Axis Title="Time" Labels="{Binding Labels}"></lvc:Axis>
                            </lvc:CartesianChart.AxisX>
                        </lvc:CartesianChart>
                    </Grid>

                    <Grid>
                        <lvc:CartesianChart Series="{Binding SeriesCollection2}" LegendLocation="Right" Margin="792,160,9.8,238" >
                            <lvc:CartesianChart.AxisY>
                                <lvc:Axis Title="Sales" LabelFormatter="{Binding YFormatter2}"></lvc:Axis>
                            </lvc:CartesianChart.AxisY>
                            <lvc:CartesianChart.AxisX>
                                <lvc:Axis Title="Month" Labels="{Binding Labels2}"></lvc:Axis>
                            </lvc:CartesianChart.AxisX>
                        </lvc:CartesianChart>
                    </Grid>

C#:

public MainWindow(){
cartchartinit();
cartchartinit2();
}

private void cartchartinit2()
    {
        SeriesCollection2 = new SeriesCollection
        {
            new Lineseries
            {
                Title = "Series 1",Values = new ChartValues<double> { 4,6,5,2,7 }
            },new Lineseries
            {
                Title = "Series 2",Values = new ChartValues<double> { 6,7,3,4,6 }
            }
        };

        Labels2 = new[] { "Jan","Feb","Mar","Apr","May" };
        YFormatter2 = value => value.ToString("C");

        //modifying the series collection will animate and update the chart
        SeriesCollection2.Add(new Lineseries
        {
            Values = new ChartValues<double> { 5,4 },Linesmoothness = 0 //straight lines,1 really smooth lines
        });

        //modifying any series values will also animate and update the chart
        SeriesCollection2[2].Values.Add(5d);

        DataContext = this;
    }

    public SeriesCollection SeriesCollection2 { get; set; }
    public string[] Labels2 { get; set; }
    public Func<double,string> YFormatter2 { get; set; }

private void cartchartinit()
    {

        SeriesCollection = new SeriesCollection
        {
            new Lineseries
            {
                Title = "Average Vehicles Gap",Values = null
            },/* new Lineseries
            {
                Title = "Avg Gap (Metre)",Values = null



            },*/

            /*new Lineseries
            {
                Title = "Series 3",7 },PointGeometry = DefaultGeometries.Square,PointGeometrySize = 15
            }*/
        };

        Labels = null;
        YFormatter = value => value.ToString("");

        

        DataContext = this;

    }
    public SeriesCollection SeriesCollection { get; set; }
    public string[] Labels { get; set; }
    public Func<double,string> YFormatter { get; set; }

当我仅使用cartchartinit()方法时,它可以工作。但是,当我添加cartchartinit2()时,它只会为以后的图表绘制图形。我做错了吗?

我们将不胜感激。

谢谢

解决方法

第一个图表为空,因为绑定源也是如此。
您评论了SeriesCollection属性的初始化,并将唯一系列项目的LineSeries.Values属性设置为null ==>这里没有数据显示。您还会遇到属性更改没有报告给绑定引擎的问题。

您的代码有几个问题。解决最重要的问题:

布局

不要将每个控件包装到Grid中。
除了渲染性能成本外,这什么都没有增加。包装网格绝对是多余的。 Grid是布局Panel,但目前您尚未将其用于元素排列。

请勿使用Margin定位网格。
这不允许您的应用程序缩放,并且基于边距的布局难以实现。
如果需要绝对定位,请使用Canvas。如果您需要相对定位,请使用Panel之类的Grid,例如用于基于列和行的布局,或者用于简单的垂直或水平排列元素的StackPanel

仅将Margin用于较小的调整,最好调整到相对屏幕位置。

从边缘看,您希望图表显示为两行两列(从左上角到右下角的对角线)。在这种情况下,请使用Grid

<Grid>
  <Grid.RowDefinitions>
    <RowDefinition Height="*" />
    <RowDefinition Height="*" />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="*" />
    <ColumnDefinition Width="*" />
  </Grid.ColumnDefinitions>

  <lvc:CartesianChart Grid.Row="0" Grid.Column="0"
                      Series="{Binding SeriesCollection}" 
                      LegendLocation="Right">
    ...
  </lvc:CartesianChart>

  <lvc:CartesianChart Grid.Row="1" Grid.Column="1"
                      Series="{Binding SeriesCollection2}" 
                      LegendLocation="Right">
    ...
  </lvc:CartesianChart>
</Grid>

如果要使图表彼此相邻对齐,只需使用StackPanel

<StackPanel Orientation="Horizontal">    
  <lvc:CartesianChart Series="{Binding SeriesCollection}" 
                      LegendLocation="Right">
    ...
  </lvc:CartesianChart>

  <lvc:CartesianChart Series="{Binding SeriesCollection2}" 
                      LegendLocation="Right">
    ...
  </lvc:CartesianChart>
</StackPanel>

数据绑定

您使用数据绑定将图表数据分配给图表。很好 但是,您将在初始化XAML绑定表达式之后 设置绑定源。由于您的所有源属性(例如SeriesCollectionSeriesCollection2都不是DependencyProperty也不引发INotifyPropertyChanged.PropertyChanged事件,因此绑定引擎不会选择这些属性的更改/分配。就您而言,它起作用,但这仅是因为在每次属性更改后通过重新分配Binding.Source来刷新this.DataContext = this
这将强制视图中的每个绑定再次初始化。

在更复杂的应用程序中,这将明显增加启动时间或导致UI缓慢。
默认情况下,WPF沿可视树继承了DataContext属性值(例如DataTemplate除外):每个子元素都隐式地共享与其父元素相同的DataContext
这意味着刷新此属性会影响整个视觉树! ==>不要仅仅因为Binding.Source被更新而刷新DataContext(尤其是Binding.Path)。

让绑定引擎处理这些更改:

无论何时预期绑定的源属性动态变化,源对象都必须将这些属性实现为DependencyProperty,或者如果该对象不是DependencyObject,则必须实现INotifyPropertyChanged

请参见Data binding overview in WPFDependency properties overview

WindowDependencyObject,因此MainWindow应该实现所有用作绑定源或绑定目标的属性,例如DependencyProerty

partial class MainWindow : Window
{
  public static readonly DependencyProperty SeriesCollectionProperty = DependencyProperty.Register(
    "SeriesCollection",typeof(SeriesCollection),typeof(MainWindow),new PropertyMetadata(default(SeriesCollection)));

  public SeriesCollection SeriesCollection
  {
    get => (SeriesCollection) GetValue(MainWindow.SeriesCollectionProperty);
    set => SetValue(MainWindow.SeriesCollectionProperty,value);
  }

  public static readonly DependencyProperty SeriesCollection2Property = DependencyProperty.Register(
    "SeriesCollection2",new PropertyMetadata(default(SeriesCollection)));

  public SeriesCollection SeriesCollection2
  {
    get => (SeriesCollection) GetValue(MainWindow.SeriesCollection2Property);
    set => SetValue(MainWindow.SeriesCollection2Property,value);
  }

  ... // Do this for all properties that serve as binding source or target

  public MainwWindow()
  {
    InitializeComponent();
    this.DataContext = this;
  }

  private void cartchartinit()
  {
    // Aside from their slightly clumsy definition,// dependency properties are used like common CLR properties
    SeriesCollection = new SeriesCollection();
  }
}

相关问答

Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其...
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。...
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbc...