Your Privacy Matters: We use our own and third-party cookies to improve your experience on our website. By continuing to use the website we understand that you accept their use. Cookie Policy
60
Possible Bug in series object
posted

Hi,

I am populating a column chart programatically from the data returned from service. The following xaml will explain how the data is coming back from the service.

<igChart:XamWebChart.Series>
                    <igChart:Series Label="Open" DataPointStyle="{StaticResource ColumnChart}" ChartType="Column">
                        <igChart:Series.Animation>
                            <igChart:Animation />
                        </igChart:Series.Animation>
                        <igChart:Series.Fill>
                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                <GradientStop Color="#FF358ECA" />
                                <GradientStop Color="#FF014E7C" Offset="1" />
                            </LinearGradientBrush>
                        </igChart:Series.Fill>
                        <igChart:Series.DataPoints>
                            <igChart:DataPoint Label="Jan" Value="25" />
                        </igChart:Series.DataPoints>
                    </igChart:Series>
                    <igChart:Series Label="Active" ChartType="Column" DataPointStyle="{StaticResource ColumnChart}">
                        <igChart:Series.Animation>
                            <igChart:Animation />
                        </igChart:Series.Animation>
                        <igChart:Series.Fill>
                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
                                <GradientStop Color="#FFA7D912" />
                                <GradientStop Color="#FF496100" Offset="1" />
                            </LinearGradientBrush>
                        </igChart:Series.Fill>
                        <igChart:Series.DataPoints>
                            <igChart:DataPoint Label="Feb" Value="15" />
                        </igChart:Series.DataPoints>
                    </igChart:Series>
                </igChart:XamWebChart.Series>

Now the problem with this is, chart renders only 1 point in x-axis with 2 values, where as it should have rendered 2 points. Please let me know if this is a bug and if you have any work-around for this.

Thanks,
Apratim

  • 30692
    Suggested Answer
    Offline posted in reply to Apratim

    Apartim,

    This behavior for the category charts is basically because they are ideally expecting tabular data, see: http://help.infragistics.com//Help/NetAdvantage/DV/2009.2/CLR3.5/html/?page=SL_DV_xamWebChart_Column_Chart.html

    In this case, and especially with silverlight, you provide this tabular data a column at a time in separate series objects, but the chart still only expects to use one column as its labels, and will not attempt to reorder, align, or fill in missing values between seperate series to account for missing or reordered labels.

    You are welcome to request this as a feature: https://ko.infragistics.com/community/ideas

    In the meantime, you may find the following sample to be quite useful. It shows how you can use some simple Linq queries to correlate your multiple series and fill in any labels that are missing from each series.

     

    The Xaml:

    <igChart:XamWebChart>
                <igChart:XamWebChart.Series>
                    <igChart:Series ChartType="Column" 
                                    DataSource="{Binding Data1}"
                                    DataMapping="Label = Label; Value = Value"
                                    />
                    <igChart:Series ChartType="Column" 
                                    DataSource="{Binding Data2}"
                                    DataMapping="Label = Label; Value = Value"
                                    />
                </igChart:XamWebChart.Series>
            </igChart:XamWebChart>
    

    The code behind:

    public class LabelUnioner
        {
            public static void UnionLabels<T>(
                IEnumerable<T> set1, IEnumerable<T> set2,
                Func<T, string> getLabel, 
                Func<string, string, int> compareLabels,
                Func<string, T> getDefault,
                out IEnumerable<T> unionedSet1, 
                out IEnumerable<T> unionedSet2)
            {
                var set1Labels = from item in set1 
                                 select getLabel(item);
                var set2Labels = from item in set2 
                                 select getLabel(item);
    
                //get the union of the labels from the two sets.
                var unionedLabels = set1Labels.Union(set2Labels);
    
                //sort the unioned labels using the provided comparison
                //function.
                List<string> sortedLabels = unionedLabels.ToList();
                sortedLabels.Sort((s1, s2) =>
                {
                    return compareLabels(s1, s2);
                });
    
                //perform an outer join on such that any items that are
                //not represented in the unioned labels will have
                //a default item inserted.
                var newd1 = from l in sortedLabels
                            join d in set1 
                            on l equals getLabel(d) into g
                            from item in
                                g.DefaultIfEmpty(getDefault(l))
                            select item;
                //perform the same outer join for the other set.
                var newd2 = from l in sortedLabels
                            join d in set2 
                            on l equals getLabel(d) into g
                            from item in
                                g.DefaultIfEmpty(getDefault(l))
                            select item;
                unionedSet1 = newd1;
                unionedSet2 = newd2;
            }
        }
    
        public partial class MainPage
            : UserControl, INotifyPropertyChanged
        {
            public MainPage()
            {
                InitializeComponent();
    
                DataContext = this;
    
                ObservableCollection<TestDataItem> d1 =
                    GetTestData1();
                ObservableCollection<TestDataItem> d2 =
                    GetTestData2();
    
    
                IEnumerable<TestDataItem> newd1;
                IEnumerable<TestDataItem> newd2;
    
                LabelUnioner.UnionLabels<TestDataItem>(
                    d1, d2,
                    (item) => item.Label,
                    (s1, s2) =>
                    {
                        //sort the month values as date times
                        //rather than strings.
                        DateTime date1 = 
                            DateTime.ParseExact(s1, "MMM", 
                            CultureInfo.CurrentCulture);
                        DateTime date2 = 
                            DateTime.ParseExact(s2, "MMM",
                            CultureInfo.CurrentCulture);
    
                        return date1.Month.CompareTo(date2.Month);
                    },
                    (label) => new TestDataItem() 
                    { 
                        Label = label, Value = 0 
                    },
                    out newd1, out newd2);
    
    
                Data1 = newd1;
                Data2 = newd2;
            }
    
            private IEnumerable<TestDataItem> data1;
            public IEnumerable<TestDataItem> Data1
            {
                get
                {
                    return data1;
                }
                set
                {
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this,
                            new PropertyChangedEventArgs("Data1"));
                    }
                    data1 = value;
                }
            }
            private IEnumerable<TestDataItem> data2;
            public IEnumerable<TestDataItem> Data2
            {
                get
                {
                    return data2;
                }
                set
                {
                    if (PropertyChanged != null)
                    {
                        PropertyChanged(this, 
                            new PropertyChangedEventArgs("Data2"));
                    }
                    data2 = value;
                }
            }
    
            private ObservableCollection<TestDataItem> GetTestData1()
            {
                ObservableCollection<TestDataItem> data =
                    new ObservableCollection<TestDataItem>()
                {
                    new TestDataItem() { Label = "Jan", Value = 2 },
                    new TestDataItem() { Label = "Mar", Value = 3 },
                    new TestDataItem() { Label = "Apr", Value = 6 }
                };
    
                return data;
            }
    
            private ObservableCollection<TestDataItem> GetTestData2()
            {
                ObservableCollection<TestDataItem> data = 
                    new ObservableCollection<TestDataItem>()
                {
                    new TestDataItem() { Label = "Feb", Value = 4 },
                    new TestDataItem() { Label = "Mar", Value = 1 },
                    new TestDataItem() { Label = "Apr", Value = 8 }
                };
    
                return data;
            }
    
            #region INotifyPropertyChanged Members
    
            public event PropertyChangedEventHandler PropertyChanged;
    
            #endregion
        }
    
        public class TestDataItem
        {
            public string Label { get; set; }
            public double Value { get; set; }
        }
    

    -Graham

  • 60
    posted in reply to Graham Murray

    Hi Gullam,

    I pretty much figured that peice by looking at the examples. But do you really think its a correct aprroach? I am calling a service, which can give me n number of series and n number of data points. Also if you see your object model they perfectly allow you to do so. Then while painting why it would only consider first series data points label.

    Also if i remember correctly all other version of charting products support this kind of data and if you think it though to make sure all the series and all the data points have value its very simple to acheive it as well, where you dont know how many and what series and datapoint data is coming your way.

    Let me know if you can think of any workarounds. Our scenario is we fetch data from SQL using group by and return it as a LIST<T> from the service.

    Thanks, Apratim

  • 30692
    Suggested Answer
    Offline posted

    Apratim,

    For this kind of series, the labels are going to be based of the first series in the chart, and there is the assumption that the seperate series will be aligned in terms of label, so something like this:

    <igChart:XamWebChart>

                <igChart:XamWebChart.Series>

                    <igChart:Series Label="Open"  ChartType="Column">

                        <igChart:Series.Animation>

                            <igChart:Animation />

                        </igChart:Series.Animation>

                        <igChart:Series.Fill>

                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">

                                <GradientStop Color="#FF358ECA" />

                                <GradientStop Color="#FF014E7C" Offset="1" />

                            </LinearGradientBrush>

                        </igChart:Series.Fill>

                        <igChart:Series.DataPoints>

                            <igChart:DataPoint Label="Jan" Value="25" />

                            <igChart:DataPoint Label="Feb" Value="0" />

                            <igChart:DataPoint Label="Mar" Value="14" />

                        </igChart:Series.DataPoints>

                    </igChart:Series>

                    <igChart:Series Label="Active" ChartType="Column" >

                        <igChart:Series.Animation>

                            <igChart:Animation />

                        </igChart:Series.Animation>

                        <igChart:Series.Fill>

                            <LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">

                                <GradientStop Color="#FFA7D912" />

                                <GradientStop Color="#FF496100" Offset="1" />

                            </LinearGradientBrush>

                        </igChart:Series.Fill>

                        <igChart:Series.DataPoints>

                            <igChart:DataPoint Label="Jan" Value="0" />

                            <igChart:DataPoint Label="Feb" Value="15" />

                            <igChart:DataPoint Label="Mar" Value="18" />

                        </igChart:Series.DataPoints>

                    </igChart:Series>

                </igChart:XamWebChart.Series>

            </igChart:XamWebChart>

    probably renders more in the way you would expect. You can fill out missing values in either series with 0 values.

    -Graham