Chart Types / Specialized charts / WinForms Floating Bar Chart
WinForms Floating Bar Chart

Floating bar charts are charts with a single or multiple bars floating between a minimum and maximum value instead of being connected to the axis. It displays information as a range of data by plotting two Y-values(low and high) per data point. Floating bars can be useful to show highs and lows in a data set, such as daily high and low temperatures, stock prices, blood pressure readings, etc.

WinForms Floating Bar Chart

In FlexChart, WinForms floating bar chart can be implemented using the Series class. To begin with, create a new Series object and specify its properties. Then, use the SymbolRendering event provided by the Series class to plot the data points on the chart.

private void Form1_Load(object sender, EventArgs e)
{
    string[] cities = { "Chicago", "New York" };
    List<CityDataItem> data = GetTemperatureData(cities, true, 7, true);
    this.flexChart1.AxisY.Min = data.Select(x => x.Data.Min(y => y.LowTemp)).Min();
    this.flexChart1.AxisY.Max = data.Select(x => x.Data.Max(y => y.HighTemp)).Max();
    foreach (var dataItem in data)
    {
        Series series = new Series()
        {
            Binding = "HighTemp",
            BindingX = "Date",
            Name = dataItem.Name,
            DataSource = dataItem.Data,
        };
        series.SymbolRendering += Series_SymbolRendering;
        this.flexChart1.Series.Add(series);
    }

    this.flexChart1.DataLabel.Content = "{seriesName}";
    this.flexChart1.DataLabel.Position = LabelPosition.Bottom;
    this.flexChart1.LabelRendering += FlexChart1_LabelRendering;

    this.flexChart1.Header.Content = "Weather Report : Monthly Temperatures";
    this.flexChart1.AxisY.Format = "0 °F";
    this.flexChart1.Options.ClusterSize = new ElementSize { SizeType = ElementSizeType.Percentage, Value = columnWidthPercentage * 100 };
    this.flexChart1.DataLabel.Overlapping = LabelOverlapping.Show;
}
private void FlexChart1_LabelRendering(object sender, RenderDataLabelEventArgs e)
{
    var temp = (Temperature)e.Item;
    e.Text = string.Format("{0:0}:{1:0}", temp.LowTemp, temp.HighTemp);
}

private void Series_SymbolRendering(object sender, RenderSymbolEventArgs e)
{
    e.Cancel = true;
    Temperature temperature = (Temperature)e.Item;
    var width = this.flexChart1.PlotRect.Width / ((List<Temperature>)this.flexChart1.Series[0].DataSource).Count * columnWidthPercentage / this.flexChart1.Series.Count;
    var bottom = 0d;
    bottom = this.flexChart1.AxisY.Convert(temperature.LowTemp);
    e.Engine.DrawRect(e.Point.X - width / 2 - 2, e.Point.Y, width - 4, bottom - e.Point.Y);
}

Note that the above sample code uses a custom method named GetTemperatureData to supply data to the chart. You can set up the data source as per your requirements.

        
private Random rnd = new Random();
public List<CityDataItem> GetTemperatureData(string[] cities, bool monthly = false, int count = 30, bool isFahrenheit = false)
{
    var data = new List<CityDataItem>();
    var startDate = new DateTime(2017, 1, 1);
    foreach (string city in cities)
    {
        var dataItem = new CityDataItem() { Name = city };
        for (int i = 0; i < count; i++)
        {
            var temp = new Temperature();
            DateTime date;
            if (monthly)
                date = startDate.AddMonths(i);
            else
                date = startDate.AddDays(i);
            temp.Date = date;
            if (date.Month <= 8)
                temp.HighTemp = rnd.Next(3 * date.Month, 8 * date.Month);
            else
                temp.HighTemp = rnd.Next((13 - date.Month - 2) * date.Month, (13 - date.Month) * date.Month);
            temp.LowTemp = temp.HighTemp - rnd.Next(6, 8);
            temp.Precipitation = (date.Month < 4 || date.Month > 8) ? rnd.Next(100, 150) : rnd.Next(150, 200);
            if (isFahrenheit) temp.HighTemp = temp.HighTemp * 1.8 + 32;
            dataItem.Data.Add(temp);
        }
        data.Add(dataItem);
    }
    return data;
}