C#图表轴标签未正确格式化

3
假设我们有一个调用远程数据库的方法,大约需要1秒钟才能完成,并返回一个DataTable(下面是模拟):
DataTable GetData()
{
    Thread.Sleep(1000); // simulated delay

    var dt = new DataTable("DataTable");
    dt.Columns.Add("DateTime", typeof(DateTime));
    dt.Columns.Add("Value", typeof(double));

    var rand = new Random();
    var date = new DateTime(2016, 1, 1);
    for (int i = 0; i < 1000; i++)
    {
        dt.Rows.Add(date, rand.NextDouble() * 100);

        date = date.AddHours(12);
    }

    return dt;
}

这个方法返回的 DataTable 用于填充一个包含单条线系列的 Chart。为什么这段代码能显示正确、格式化良好的 DateTime X 轴标签:
async void MainForm_Load(object sender, EventArgs e)
{
    var data = GetData();
    chart.DataSource = data;
    chart.DataBind();
}

具有DateTime X轴的图表

这段代码显示的X轴标签不正确、未格式化?

async void MainForm_Load(object sender, EventArgs e)
{
    var data = await Task.Run(() => GetData());
    chart.DataSource = data;
    chart.DataBind();
}

请注意,即使使用第二个版本,删除Thread.Sleep()调用也可以解决此问题。

带有破碎X轴的图表

1个回答

1
答案在 chart.Series[0].XValueType 中。
首先,有几个声明:
  1. XValueType默认为Auto,如果没有明确指定,在Paint事件之前的某个地方会被解析为特定类型。

    这不是很明显,我是通过反编译源代码发现的;如果您想跟随我的研究,以下是一些里程碑:

    • Chart构造函数:

      this._dataManager.Initialize();

    • DataManager.Initialize:

      chartImage.BeforePaint += ChartPicture_BeforePaint

    • DataManager.ChartPicture_BeforePaint
    • DataManager.PrepareData
    • Series.PrepareData =>

      if (this._xValueType == ChartValueType.Auto) { this._xValueType = ChartValueType.Double;

  2. DataBind将尝试根据DataSourceAuto解析为特定类型。如果它不是Auto,它将不会尊重DataSource中的数据类型。

好的,那么在你的示例中发生了什么:

  1. 当您不使用任务时,整个 Form_Load 的主体会同步执行; 当您在图表上调用 DataBind 时,它对于 XValueTypeAuto,并且基于提供的 DataSource 解析为 DateTime

  2. 当您使用带有睡眠的任务时,在初始化 DataSource 之前会发生 Paint 事件,它将 XValueType 解析为 Double。在此之后绑定 DataSource,它使用 DateTime 的浮点表示。

如何解决所有这些问题?有很多方法,但所有方法都基于图表值类型:

  • Form_Load 中明确指定值类型
  • DataBind 正好之前删除系列并添加新系列
  • DataBind 之前明确指定值类型
  • ...

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接