Have a grid of 3 columns with 2 columns as Text and 3rd as a chart in Telerik 2015 WinForms
1 Answer 21 Views
Om Pushkara deep
Top achievements
Rank 2
Iron
Iron
Iron
Om Pushkara deep asked on 10 Jun 2021, 10:47 AM

Hi ,

I am trying to create a page with 3 columns. Date and Percent are the first 2 columns . The 3rd column will be a range bar chart where the time span across 24 hours will be in x-axis (orientation to the top) and the date again will be on the left (we can hide the label) . It might not necessarily be a gridview , but if it is that would be great . Let me attach the mock , I tried to do the 2 columns separately and the chart separately but wanted to integrate it as a single grid . 

 

Much appreciated for the help in advance.

Sample Code that i did to achieve the chart (Grid view is pretty straight forward and ignored in the below code):

 


  private void LoadBarChart()
        {

            this.radChartView1.AreaType = ChartAreaType.Cartesian;
            this.radChartView1.ChartElement.AngleTransform = 90;
            RangeBarSeries rangeBarSeries = new RangeBarSeries("End Time", "Start Time", "Summarization Date");

            rangeBarSeries.DataPoints.Add(new RangeDataPoint(DateTime.Now.TimeOfDay.TotalMinutes + 14, DateTime.Now.TimeOfDay.TotalMinutes + 10, "6/8/2021"));
            rangeBarSeries.DataPoints.Add(new RangeDataPoint(DateTime.Now.TimeOfDay.TotalMinutes + 7, DateTime.Now.TimeOfDay.TotalMinutes + 5, "6/8/2021"));
            rangeBarSeries.DataPoints.Add(new RangeDataPoint(DateTime.Now.TimeOfDay.TotalMinutes + 4, DateTime.Now.TimeOfDay.TotalMinutes + 2, "6/8/2021"));


            rangeBarSeries.DataPoints.Add(new RangeDataPoint(DateTime.Now.TimeOfDay.TotalMinutes + 30, DateTime.Now.TimeOfDay.TotalMinutes + 10, "6/7/2021"));
            rangeBarSeries.DataPoints.Add(new RangeDataPoint(DateTime.Now.TimeOfDay.TotalMinutes + 7, DateTime.Now.TimeOfDay.TotalMinutes + 5, "6/7/2021"));



            CategoricalAxis horizontalAxis = new CategoricalAxis();

            //horizontalAxis.Title = "Summarization Days";
            horizontalAxis.ClipLabels = false;
            horizontalAxis.LabelRotationAngle = -90;
            horizontalAxis.LabelFitMode = AxisLabelFitMode.Rotate;

            horizontalAxis.PlotMode = AxisPlotMode.BetweenTicks;
            rangeBarSeries.HorizontalAxis = horizontalAxis;


            this.radChartView1.Series.Add(rangeBarSeries);

            rangeBarSeries.VerticalAxis.LabelFormatProvider = new MyFormatProvider();
            //rangeBarSeries.VerticalAxis.Title = "Time of the day";
            rangeBarSeries.VerticalAxis.ClipLabels = false;
            rangeBarSeries.VerticalAxis.LabelRotationAngle = -90;
            rangeBarSeries.VerticalAxis.LabelFitMode = AxisLabelFitMode.Rotate;

            LinearAxis verticalAxis = radChartView1.Axes.Get<LinearAxis>(1);
            verticalAxis.Minimum = 0; //Minutes 0:00
            verticalAxis.Maximum = 1380; //Minutes 23:00
            verticalAxis.MajorStep = 60; //60 minutes in an hour

            CartesianArea area = this.radChartView1.GetArea<CartesianArea>();
            area.ShowGrid = true;

            CartesianGrid grid = area.GetGrid<CartesianGrid>();
            grid.DrawVerticalStripes = true;
            grid.DrawHorizontalStripes = false;
        }


        public class MyFormatProvider : IFormatProvider, ICustomFormatter
        {
            public object GetFormat(Type formatType)
            {
                return this;
            }
            public string Format(string format, object arg, IFormatProvider formatProvider)
            {
                int totalminutes = Convert.ToInt32(arg);

                TimeSpan timeSpan = TimeSpan.FromMinutes(totalminutes);

                return timeSpan.ToString(@"hh\:mm");
            }
        }

1 Answer, 1 is accepted

Sort by
1
Accepted
Dess | Tech Support Engineer, Principal
Telerik team
answered on 11 Jun 2021, 10:42 AM
Hello,  


RadGridView provides a convenient way to construct custom cells and integrate any desired elements. A sample approach is demonstrated in the following help article: https://docs.telerik.com/devtools/winforms/controls/gridview/cells/creating-custom-cells

Following this approach, I have prepared the following code snippet which result is illustrated below. Note that this is just a sample approach and it may not cover all possible cases. Feel free to modify and extend it in a way which suits your requirements best.

 

        public RadForm1()
        {
            InitializeComponent();

            this.radGridView1.Columns.Add("Column1");
            this.radGridView1.Columns.Add("Column2");
            ChartColumn customColumn = new ChartColumn("Chart column");
            this.radGridView1.Columns.Add(customColumn);
            this.radGridView1.AutoSizeColumnsMode = GridViewAutoSizeColumnsMode.Fill;

            for (int i = 0; i < 10; i++)
            {
                this.radGridView1.Rows.Add(i, i, i);
            }
            this.radGridView1.TableElement.RowHeight = 200;
            this.radGridView1.AllowAddNewRow = false;
        }

        public class ChartCell : GridDataCellElement
        { 
            public ChartCell(GridViewColumn column, GridRowElement row) : base(column, row)
            {
            }

            RadChartElement chart = new RadChartElement();
 
            protected override void CreateChildElements()
            {
                base.CreateChildElements();
                LoadBarChart();
                this.Children.Add(chart);
            }

            private void LoadBarChart()
            {
                chart.View.AreaType = ChartAreaType.Cartesian; 
                chart.AngleTransform = 90;
                RangeBarSeries rangeBarSeries = new RangeBarSeries("End Time", "Start Time", "Summarization Date");

                rangeBarSeries.DataPoints.Add(new RangeDataPoint(DateTime.Now.TimeOfDay.TotalMinutes + 14, DateTime.Now.TimeOfDay.TotalMinutes + 10, "6/8/2021"));
                rangeBarSeries.DataPoints.Add(new RangeDataPoint(DateTime.Now.TimeOfDay.TotalMinutes + 7, DateTime.Now.TimeOfDay.TotalMinutes + 5, "6/8/2021"));
                rangeBarSeries.DataPoints.Add(new RangeDataPoint(DateTime.Now.TimeOfDay.TotalMinutes + 4, DateTime.Now.TimeOfDay.TotalMinutes + 2, "6/8/2021"));

                rangeBarSeries.DataPoints.Add(new RangeDataPoint(DateTime.Now.TimeOfDay.TotalMinutes + 30, DateTime.Now.TimeOfDay.TotalMinutes + 10, "6/7/2021"));
                rangeBarSeries.DataPoints.Add(new RangeDataPoint(DateTime.Now.TimeOfDay.TotalMinutes + 7, DateTime.Now.TimeOfDay.TotalMinutes + 5, "6/7/2021"));

                CategoricalAxis horizontalAxis = new CategoricalAxis();

                //horizontalAxis.Title = "Summarization Days";
                horizontalAxis.ClipLabels = false;
                horizontalAxis.LabelRotationAngle = -90;
                horizontalAxis.LabelFitMode = AxisLabelFitMode.Rotate;

                horizontalAxis.PlotMode = AxisPlotMode.BetweenTicks;
                rangeBarSeries.HorizontalAxis = horizontalAxis;

                chart.View.Series.Add(rangeBarSeries);

                rangeBarSeries.VerticalAxis.LabelFormatProvider = new MyFormatProvider();
                //rangeBarSeries.VerticalAxis.Title = "Time of the day";
                rangeBarSeries.VerticalAxis.ClipLabels = false;
                rangeBarSeries.VerticalAxis.LabelRotationAngle = -45;
                rangeBarSeries.VerticalAxis.LabelFitMode = AxisLabelFitMode.Rotate;

                LinearAxis verticalAxis = chart.View.Axes.Get<LinearAxis>(1);
                verticalAxis.Minimum = 0; //Minutes 0:00
                verticalAxis.Maximum = 1380; //Minutes 23:00
                verticalAxis.MajorStep = 60; //60 minutes in an hour

                CartesianArea area = chart.View.GetArea<CartesianArea>();
                area.ShowGrid = true;

                CartesianGrid grid = area.GetGrid<CartesianGrid>();
                grid.DrawVerticalStripes = true;
                grid.DrawHorizontalStripes = false;
            }

            protected override void SetContentCore(object value)
            {
                base.SetContentCore(value);
                //you can synchronize the chart data points according to the cell value if necessary 
            }
            
            protected override Type ThemeEffectiveType
            {
                get
                {
                    return typeof(GridDataCellElement);
                }
            }

            public override bool IsCompatible(GridViewColumn data, object context)
            {
                return data is ChartColumn && context is GridDataRowElement;
            }
        }

        public class ChartColumn : GridViewDataColumn
        {
            public ChartColumn(string fieldName) : base(fieldName)
            {
            }

            public override Type GetCellType(GridViewRowInfo row)
            {
                if (row is GridViewDataRowInfo)
                {
                    return typeof(ChartCell);
                }
                return base.GetCellType(row);
            }
        }

        public class MyFormatProvider : IFormatProvider, ICustomFormatter
        {
            public object GetFormat(Type formatType)
            {
                return this;
            }

            public string Format(string format, object arg, IFormatProvider formatProvider)
            {
                int totalminutes = Convert.ToInt32(arg);

                TimeSpan timeSpan = TimeSpan.FromMinutes(totalminutes);

                return timeSpan.ToString(@"hh\:mm");
            }
        }

I hope this information helps. If you need any further assistance please don't hesitate to contact me. 

Regards,
Dess | Tech Support Engineer, Sr.
Progress Telerik

Virtual Classroom, the free self-paced technical training that gets you up to speed with Telerik and Kendo UI products quickly just got a fresh new look + new and improved content including a brand new Blazor course! Check it out at https://learn.telerik.com/.

Om Pushkara deep
Top achievements
Rank 2
Iron
Iron
Iron
commented on 11 Jun 2021, 11:25 AM

Works really cool .. Much appreciated .. Thanks a lot . I dont know where to review and give you a thumbs-up.

One final thing where i can set first column and second column to 10% area and the chart (3rd column) to 80% area?
Dess | Tech Support Engineer, Principal
Telerik team
commented on 11 Jun 2021, 11:54 AM

I am glad that the suggested reply was useful for you. You can have a look at the following article in order to learn how to resize the columns in RadGridView

https://docs.telerik.com/devtools/winforms/controls/gridview/columns/resizing-columns-programatically

As to the "thumbs-up", you can mark the reply as answer or vote for it with the up/down arrows.

 

 
Om Pushkara deep
Top achievements
Rank 2
Iron
Iron
Iron
commented on 11 Jun 2021, 01:27 PM

One more final question that struck my mind . What about i wanna have different data points for each chart column . For instance 6th July data in row 1 chart column and 7th July data in row 2 chart column
Dess | Tech Support Engineer, Principal
Telerik team
commented on 11 Jun 2021, 02:01 PM

If you refer to the previously mentioned article about creating custom cells, https://docs.telerik.com/devtools/winforms/controls/gridview/cells/creating-custom-cells , you will notice the overridden SetContentCore method where the custom element, RadProgressBarElement in this example, is synchronized with the value of the cell. In a similar way you can override the SetContentCore method of the custom cell and manipulate the chart's DataPoints collection and add/remove the desired points according to the cell's Value you store. Thus, for each chart cell you may have different values. It is up to you how exactly you will store the values per each row. It is just necessary to extract this value in the SetContentCore method and populate the chart with DataPoints

I hope this information helps.
Om Pushkara deep
Top achievements
Rank 2
Iron
Iron
Iron
commented on 11 Jun 2021, 03:42 PM

Okay I got it partially. But where will you set the data points for the setcontentcore method to fetch it .

For example : the datapoint for first row is

6th June high 6 low 2
6th June high 10 low 8

the datapoint for second row is

7th June high 6 low 2
7th June high 10 low 8
Om Pushkara deep
Top achievements
Rank 2
Iron
Iron
Iron
commented on 12 Jun 2021, 06:17 PM

I have achieved the result mentioned in the above comment . SetContentCore does a really great job . Much appreciated once again. Kudos to you ..
Om Pushkara deep
Top achievements
Rank 2
Iron
Iron
Iron
commented on 14 Jun 2021, 07:22 AM

I have one more clarification while setting the chart . SetContentCore() method gets called repeatedly when i try to resize the Radgridview . Any way/event to cancel this call ?
Dess | Tech Support Engineer, Principal
Telerik team
commented on 16 Jun 2021, 06:34 AM

It is absolutely expected to have the SetContentCore method called repeatedly when you resize RadGridView or when any user interaction is performed. This process can't be stopped. Due to the UI virtualization in RadGridView, cell elements are created only for currently visible cells and are being reused during operations like scrolling, filtering, grouping , resizing and so on. In order to prevent displaying wrong information to the columns' cell elements (because of the cell reuse), all data synchronization should be performed in the SetContentCore method.
Asked by
Om Pushkara deep
Top achievements
Rank 2
Iron
Iron
Iron
Answers by
Dess | Tech Support Engineer, Principal
Telerik team
Share this question
or