SeriesMapping Duplication

8 posts, 0 answers
  1. digitall
    digitall avatar
    169 posts
    Member since:
    Jun 2006

    Posted 08 Nov 2011 Link to this post

    I'm extremely new to Silverlight and also charting and running into an issue that I'm hoping is very simple. I downloaded the PDF/Tutorial combo and modeled a manual chart (using fake data - I'll worry about real stuff later) after the example provided by the "03_Binding" project. The class I am creating the chart from (with an ObservableItemCollection, part of the Telerik namespace) has the following definition:
    public class AccountReportItem : INotifyPropertyChanged
    {
    private string _EntityName = string.Empty;
    private string _ReviewItemType = string.Empty;
    private string _ReviewItem = string.Empty;
    private decimal _SuccessRate = 0.0M;
    public string EntityName
    {
    get { return this._EntityName; }
    set
    {
    this._EntityName = value;
    this.RaisePropertyChanged("EntityName");
    }
    }
    public string ReviewItemType
    {
    get { return this._ReviewItemType; }
    set
    {
    this._ReviewItemType = value;
    this.RaisePropertyChanged("ReviewItemType");
    }
    }
    public string ReviewItem
    {
    get { return this._ReviewItem; }
    set
    {
    this._ReviewItem = value;
    this.RaisePropertyChanged("ReviewItem");
    }
    }
    public decimal SuccessRate
    {
    get { return this._SuccessRate; }
    set
    {
    this._SuccessRate = value;
    this.RaisePropertyChanged("SuccessRate");
    }
    }
    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string name)
    {
    if (this.PropertyChanged != null)
    this.PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
    #endregion
    }

    The "parent" (AccountReport) object has the ObservableItemCollection which contains these items. As part of the constructor for that class, I create a total of 25 instances of it and add those to the parent object's Items property. The full declaration is here:
    public class AccountReport : INotifyPropertyChanged
    {
    public AccountReport()
    {
    this.CategoryName = "Section Header";
    this.Items = new ObservableItemCollection<AccountReportItem>();
    var entities = new string[] { "Entity 1", "Entity 2", "Entity 3", "Entity 4", "Entity 5" };
    var rnd = new Random();
    foreach (var entity in entities)
    {
    this.Items.Add(new AccountReportItem
    {
    ReviewItem = "Item #1 Content",
    EntityName = entity,
    SuccessRate = rnd.Next(1, 100)
    });
    this.Items.Add(new AccountReportItem
    {
    ReviewItem = "Item #2 Content",
    EntityName = entity,
    SuccessRate = rnd.Next(0, 28)
    });
    this.Items.Add(new AccountReportItem
    {
    ReviewItem = "Item #3 Content",
    EntityName = entity,
    SuccessRate = rnd.Next(0, 59)
    });
    this.Items.Add(new AccountReportItem
    {
    ReviewItem = "Item #4 Content",
    EntityName = entity,
    SuccessRate = rnd.Next(0, 18)
    });
    this.Items.Add(new AccountReportItem
    {
    ReviewItem = "Item #5 Content",
    EntityName = entity,
    SuccessRate = rnd.Next(0, 7)
    });
    }
    }
    private string _CategoryName = string.Empty;
    public string CategoryName
    {
    get { return this._CategoryName; }
    set
    {
    this._CategoryName = value;
    this.RaisePropertyChanged("CategoryName");
    }
    }
    private ObservableItemCollection<AccountReportItem> _Items;
    public ObservableItemCollection<AccountReportItem> Items
    {
    get { return this._Items; }
    set
    {
    this._Items = value;
    this.RaisePropertyChanged("Items");
    }
    }
    #region INotifyPropertyChanged Members
    public event PropertyChangedEventHandler PropertyChanged;
    private void RaisePropertyChanged(string name)
    {
    if (this.PropertyChanged != null)
    this.PropertyChanged(this, new PropertyChangedEventArgs(name));
    }
    #endregion
    }

    To generate the report itself, I use the Page_Loaded event, create an instance of the above class (which creates the children for me) and assign the ItemsSource of the chart equal to the 25 objects created as part of my sample data. I have also tried not setting the ItemsSource property of the chart, but instead using the ItemsSource of each SeriesMapping but the result was identical. Below is the code I was using to generate the report:
    private void Page_Loaded(object sender, RoutedEventArgs e)
    {
    //create the parent object - this creates the 25 children automatically
    AccountReport data = new AccountReport();
    //assign the children to the chart's itemssource
    chart.ItemsSource = data.Items;
    chart.DefaultView.ChartLegend.Header = data.CategoryName;
    var entities = (from s in data.Items select s.EntityName).Distinct().ToList();
    foreach (var entity in entities)
    {
    var map = this.AddSeriesMapping(new HorizontalBarSeriesDefinition(), entity, "ReviewItem", "SuccessRate");
    //made no difference even though chart.ItemsSource was null
    //chart.ItemsSource = (from r in data.Items where r.EntityName == entity select r).ToList();
    chart.SeriesMappings.Add(map);
    }
    chart.DefaultView.ChartArea.AxisX.MinValue = 0;
    chart.DefaultView.ChartArea.AxisX.MaxValue = 100;
    chart.DefaultView.ChartArea.AxisX.LayoutMode = AxisLayoutMode.Inside;
    }
    private SeriesMapping AddSeriesMapping(ISeriesDefinition seriesDefinition, string legendLabel, string categoryName, string fieldName)
    {
    // add mapping for the series
    SeriesMapping mapping = new SeriesMapping()
    {
    SeriesDefinition = seriesDefinition,
    LegendLabel = legendLabel
    };
    // add item mapping for each property in the item
    mapping.ItemMappings.Add(new ItemMapping()
    {
    DataPointMember = DataPointMember.LegendLabel
    });
    mapping.ItemMappings.Add(new ItemMapping()
    {
    DataPointMember = Telerik.Windows.Controls.Charting.DataPointMember.XCategory,
    FieldName = categoryName
    });
    mapping.ItemMappings.Add(new ItemMapping()
    {
    DataPointMember = DataPointMember.YValue,
    FieldName = fieldName
    });
    return mapping;
    }

    The attachment shows what is happening. Overall the chart is exactly how I want it except that each SeriesMapping seems to assign each LegendLabel DataPointMember all the values which is incorrect. Using that screenshot, and referencing "Item #5 Content", it's safe to say one LegendLabel entry had a value of "0", one had a "3", two had "4" and one had a "5" but each one didn't all have all values like it appears to show. I'm confident this is an easy fix, but I'm at a loss as to how to do it. Suggestions?

    One other unrelated thing - The order of my items seems to get inverted when this runs. How do I change that?
  2. Evgenia
    Admin
    Evgenia avatar
    1406 posts

    Posted 10 Nov 2011 Link to this post

    Hi Digitall,

    It seems that you are on the right way. You managed to bind the data correctly using our Manual Series Mappings. However what you need is to group the underlying data based on the EntityName property. For such cases RadChart presented the Grouping function i.e. there is no need to use LINQ's Distinct method to remove duplicated elements in your datasource. More information about grouping the Chart can be found here.
    Meanwhile you may find your sample project modified and attached.

    Regards,
    Evgenia
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  3. DevCraft banner
  4. digitall
    digitall avatar
    169 posts
    Member since:
    Jun 2006

    Posted 10 Nov 2011 Link to this post

    Perfect! That did exactly what I needed it to do. One remaining piece that I hadn't mentioned originally (grouping reminded me of this), the "ReviewItem" properties need to also be grouped according to "ReviewItemType". Using the example below, the first three ReviewItem entries ("Item #1 Content", "Item #2 Content" and "Item #3 Content") would all have a ReviewItemType value of "Group #1" and the other two entries ("Item #4 Content" and "Item #5 Content") would have a ReviewItemType of "Group #2".

    Nothing else is affected by this except the display to logically show the grouped items. I won't be doing aggregates with it or anything like that - just separating them by Type.
  5. digitall
    digitall avatar
    169 posts
    Member since:
    Jun 2006

    Posted 12 Nov 2011 Link to this post

    Anyone?
  6. Evgenia
    Admin
    Evgenia avatar
    1406 posts

    Posted 15 Nov 2011 Link to this post

    Hi Scott,

    To be able to achieve this you should add one more Grouping descriptor - where you group by "ReviewItemType":

    mapping.GroupingSettings.GroupDescriptors.Add(new ChartGroupDescriptor("ReviewItemType"));
    mapping.GroupingSettings.GroupDescriptors.Add(new ChartGroupDescriptor("EntityName"));

    More information about Grouping can be found in our help topic as well as in our online demo.

    Regards,
    Evgenia
    the Telerik team

    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>

  7. Scott Salyer
    Scott Salyer avatar
    14 posts
    Member since:
    Apr 2009

    Posted 15 Nov 2011 Link to this post

    I had already tried that and it didn't work. It added the groups to the legend on the right (with "EntityName") which isn't what I intended. Instead, I need the groups to be with the item labels to just split the data into two sections. Using the code already posted, this would be the area I need to get grouped:

    //this needs to be split into one of two groups visually - no bar charts and no aggregates for it. just visually separating them
    mapping.ItemMappings.Add(new ItemMapping()
                {
                    DataPointMember = Telerik.Windows.Controls.Charting.DataPointMember.XCategory,
                    FieldName = categoryName
                });

  8. digitall
    digitall avatar
    169 posts
    Member since:
    Jun 2006

    Posted 15 Nov 2011 Link to this post

    Sorry, I accidentally posted that from the wrong account - that is the one with the support license, this is my personal one. If I use the example from the demo site you mention with the "Omega market financial results", select the "Quarterly" option which should give you four groups of data - Q1, Q2, Q3 and Q4. Using that, I would need to split Q1/Q2/Q3 into one group (hierarchically, no aggregates, no corresponding graph/bar) and Q4 into a separate group. Same chart, same number of bars, just splitting the visuals into two groups like a parent/child relationship. How might I accomplish that?
  9. Evgenia
    Admin
    Evgenia avatar
    1406 posts

    Posted 18 Nov 2011 Link to this post

    Hi Digitall,

    In order to define the different level of the drill down hierarchy you have to use the HierachicalViewDescriptors property of the RadChart control. More information can be found in this help topic as well as in our demo. You can either specify the drill down in a single chart area or in multiple chart areas as shown in our online documentation linked above.

    All the best,
    Evgenia
    the Telerik team
    Explore the entire Telerik portfolio by downloading the Ultimate Collection trial package. Get it now >>
Back to Top
DevCraft banner