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:
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:
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:
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?
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?