Hi,
How to bind (SL-DV) xamDataChart to Microsoft SQL Server Data Source(RDBMS)?
This is really urgent requirement. If anyone has any sample/link please do reply.
Thanks & Regards,
Sandip
Hello Graham,
I am newbie to xamDataChart. I would like to use OLAP axes with sql server database. I have used LInq to sql for database connection. Here is my MainPage.xaml. code
<UserControl x:Class="SilverlightApplication1.MainPage"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400" xmlns:ig="http://schemas.infragistics.com/xaml" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk" Loaded="UserControl_Loaded">
<Grid x:Name="LayoutRoot" Background="White" Height="315" Width="533">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<!--<ig:XamDataChart HorizontalAlignment="Left" Margin="22,12,0,0" Name="xamDataChart1" VerticalAlignment="Top" Height="125" Width="297" />-->
<ig:XamDataChart
Name="xamDataChart1" HorizontalZoomable="True" HorizontalZoombarVisibility="Visible">
<ig:XamDataChart.Axes>
<!--<ig:CategoryXAxis
x:Name="xAxis"
ItemsSource="{Binding}"
Label="{}{TotalBill}"/>-->
<!--<ig:OlapXAxis x:Name="olapXAxis"
DataSource="{StaticResource XmlaDataSource}"
YAxis="{Binding ElementName=xmYAxis1}"
/>-->
<ig:OlapXAxis
OlapAxisSource="Columns"
YAxis="{Binding ElementName=yAxis}"/>
<ig:NumericYAxis
x:Name="yAxis"/>
</ig:XamDataChart.Axes>
<ig:XamDataChart.Series>
<ig:LineSeries
XAxis="{Binding ElementName=xAxis}"
YAxis="{Binding ElementName=yAxis}"
ValueMemberPath="TotalPay"/>
</ig:XamDataChart.Series>
</ig:XamDataChart>
</Grid>
</UserControl>
Sandip,
The way that the CategoryXAxis works is that if you are plotting multiple series on it, they should all have the same labels and their items should be in the same order. If your data doesn't look like that, you can expand it in your viewmodel by doing some left joins in LINQ. You could also, alternatively do the left joins down in your data tier.
Here's a modified version of the view model classes that use LINQ to fill in the missing values and assert that the order items appear in the same label order for each order:
public class OrdersChartViewModel : INotifyPropertyChanged { private IList<OrderViewModel> _orderViewModels = new List<OrderViewModel>(); private EntitySet<Order> _model; private Axis _xAxis; private Axis _yAxis; public OrdersChartViewModel( EntitySet<Order> orders, Axis xAxis, Axis yAxis) { _xAxis = xAxis; _yAxis = yAxis; _model = orders; _model.EntityAdded += Orders_EntityAdded; Refresh(); } private void Refresh() { var series = new SeriesCollection(); _orderViewModels.Clear(); foreach (var order in _model) { var vm = new OrderViewModel(order, _xAxis, _yAxis); _orderViewModels.Add(vm); series.Add(vm.Series); } if (_orderViewModels.Any()) { IEnumerable<string> uniqueItemNames = new List<string>() { }; foreach (var order in _orderViewModels) { uniqueItemNames = order.Items.Select((item) => item.Label) .Distinct() .Union(uniqueItemNames) .ToList(); } var uniqueItemNamesList = uniqueItemNames.ToList(); uniqueItemNamesList.Sort(); uniqueItemNames = uniqueItemNamesList; foreach (var order in _orderViewModels) { order.AddEmptyItems(uniqueItemNames); } First = _orderViewModels.First().Items; } Series = series; } void Orders_EntityAdded( object sender, EntityCollectionChangedEventArgs<Order> e) { Refresh(); } private IEnumerable _first; public IEnumerable First { get { return _first; } set { _first = value; RaisePropertyChanged("First"); } } private SeriesCollection _series; public SeriesCollection Series { get { return _series; } set { _series = value; RaisePropertyChanged("Series"); } } private void RaisePropertyChanged(string p) { if (PropertyChanged != null) { PropertyChanged( this, new PropertyChangedEventArgs(p)); } } public event PropertyChangedEventHandler PropertyChanged; } class OrderViewModel : INotifyPropertyChanged { private Order _model; public OrderViewModel(Order order, Axis xAxis, Axis yAxis) { var series = new ColumnSeries(); _model = order; series.XAxis = xAxis as CategoryXAxis; series.YAxis = yAxis as NumericYAxis; series.ValueMemberPath = "Quantity"; series.Title = _model.OrderTitle; _model.OrderLines.EntityAdded += Model_EntityAdded; RefreshItems(); series.ItemsSource = Items; Series = series; } void Model_EntityAdded( object sender, EntityCollectionChangedEventArgs<OrderLine> e) { RefreshItems(); } private void RefreshItems() { if (Items == null) { Items = new OrderLineViewModels( _model.OrderLines); } else { Items.Clear(); foreach ( var vm in new OrderLineViewModels( _model.OrderLines)) { Items.Add(vm); } } } private Series _series; public Series Series { get { return _series; } set { _series = value; RaisePropertyChanged("Series"); } } private OrderLineViewModels _items; public OrderLineViewModels Items { get { return _items; } set { _items = value; RaisePropertyChanged("Items"); } } private void RaisePropertyChanged(string p) { if (PropertyChanged != null) { PropertyChanged( this, new PropertyChangedEventArgs(p)); } } public event PropertyChangedEventHandler PropertyChanged; internal void AddEmptyItems(IEnumerable<string> uniqueItemNames) { var eliminateDuplicates = from item in Items group item by item.Label into groupedByLabel select new OrderLineViewModel() { Label = groupedByLabel.Key, Quantity = groupedByLabel.Sum((i) => i.Quantity) }; var withEmpty = from name in uniqueItemNames join item in eliminateDuplicates on name equals item.Label into nameItemJoin from item in nameItemJoin.DefaultIfEmpty() select new OrderLineViewModel { Label = name, Quantity = item == null ? 0 : item.Quantity }; IList<OrderLineViewModel> toAdd = withEmpty.ToList(); Items.Clear(); foreach (var orderLine in toAdd) { Items.Add(orderLine); } } } public class OrderLineViewModel : INotifyPropertyChanged { public OrderLineViewModel() { } public OrderLineViewModel(OrderLine orderLine) { Label = orderLine.ItemName; double quantity; if (!double.TryParse( orderLine.Quantity, out quantity)) { quantity = 0.0; } Quantity = quantity; } private string _label; public string Label { get { return _label; } set { _label = value; RaisePropertyChanged("Label"); } } private double _quantity; public double Quantity { get { return _quantity; } set { _quantity = value; RaisePropertyChanged("Quantity"); } } private void RaisePropertyChanged(string p) { if (PropertyChanged != null) { PropertyChanged( this, new PropertyChangedEventArgs(p)); } } public event PropertyChangedEventHandler PropertyChanged; } public class OrderLineViewModels : ObservableCollection<OrderLineViewModel> { public OrderLineViewModels( IEnumerable<OrderLine> orderLines) { foreach (OrderLine order in orderLines) { Add(new OrderLineViewModel(order)); } } }
As to changing the chart type, do you mean at design time or do you mean letting the user select how to view the data dynamically? Hope this helps!
-Graham
Thanks Graham,
If my OrderLine has different Item then it is not appearing on my chart.Here is data. In ths case Pen is not appearing on chart.
Another Question is how to change chart type..?
Thanks in advance.
The resulting chart:
Here is a crash course in how you might use a technology like Ria Services with the xamDataChart.
Define the chart in xaml like this:
<Grid x:Name="LayoutRoot" Background="White"> <Grid.ColumnDefinitions> <ColumnDefinition /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <igChart:XamDataChart x:Name="theChart" Legend="{Binding ElementName=legend}"> <igChart:XamDataChart.Axes> <igChart:CategoryXAxis x:Name="xAxis" ItemsSource="{Binding First}" Label="{}{Label}" /> <igChart:NumericYAxis x:Name="yAxis"/> </igChart:XamDataChart.Axes> </igChart:XamDataChart> <igChart:Legend x:Name="legend" Grid.Column="1" /> </Grid>
And here is the code behind:
public partial class MainPage : UserControl { OrdersChartViewModel _vm = null; public MainPage() { InitializeComponent(); OrderContext context = new OrderContext(); context.Load<Order>(context.GetOrdersQuery()); context.Load<OrderLine>(context.GetOrderLinesQuery()); var x = theChart.Axes. OfType<CategoryXAxis>().First(); var y = theChart.Axes. OfType<NumericYAxis>().First(); _vm = new OrdersChartViewModel( context.Orders,x,y); _vm.PropertyChanged += vm_PropertyChanged; RefreshSeries(); DataContext = _vm; } void vm_PropertyChanged(object sender, PropertyChangedEventArgs e) { if (e.PropertyName == "Series") { RefreshSeries(); } } private void RefreshSeries() { theChart.Series.Clear(); foreach (Series s in _vm.Series) { theChart.Series.Add(s); } } } public class OrdersChartViewModel : INotifyPropertyChanged { private IList<OrderViewModel> _orderViewModels = new List<OrderViewModel>(); private EntitySet<Order> _model; private Axis _xAxis; private Axis _yAxis; public OrdersChartViewModel( EntitySet<Order> orders, Axis xAxis, Axis yAxis) { _xAxis = xAxis; _yAxis = yAxis; _model = orders; _model.EntityAdded += Orders_EntityAdded; Refresh(); } private void Refresh() { var series = new SeriesCollection(); _orderViewModels.Clear(); foreach (var order in _model) { var vm = new OrderViewModel(order, _xAxis, _yAxis); _orderViewModels.Add(vm); series.Add(vm.Series); } if (_orderViewModels.Any()) { First = _orderViewModels.First().Items; } Series = series; } void Orders_EntityAdded( object sender, EntityCollectionChangedEventArgs<Order> e) { Refresh(); } private IEnumerable _first; public IEnumerable First { get { return _first; } set { _first = value; RaisePropertyChanged("First"); } } private SeriesCollection _series; public SeriesCollection Series { get { return _series; } set { _series = value; RaisePropertyChanged("Series"); } } private void RaisePropertyChanged(string p) { if (PropertyChanged != null) { PropertyChanged( this, new PropertyChangedEventArgs(p)); } } public event PropertyChangedEventHandler PropertyChanged; } class OrderViewModel : INotifyPropertyChanged { private Order _model; public OrderViewModel(Order order, Axis xAxis, Axis yAxis) { var series = new ColumnSeries(); _model = order; series.XAxis = xAxis as CategoryXAxis; series.YAxis = yAxis as NumericYAxis; series.ValueMemberPath = "Quantity"; series.Title = _model.OrderTitle; _model.OrderLines.EntityAdded += Model_EntityAdded; RefreshItems(); series.ItemsSource = Items; Series = series; } void Model_EntityAdded( object sender, EntityCollectionChangedEventArgs<OrderLine> e) { RefreshItems(); } private void RefreshItems() { if (Items == null) { Items = new OrderLineViewModels( _model.OrderLines); } else { Items.Clear(); foreach ( var vm in new OrderLineViewModels( _model.OrderLines)) { Items.Add(vm); } } } private Series _series; public Series Series { get { return _series; } set { _series = value; RaisePropertyChanged("Series"); } } private OrderLineViewModels _items; public OrderLineViewModels Items { get { return _items; } set { _items = value; RaisePropertyChanged("Items"); } } private void RaisePropertyChanged(string p) { if (PropertyChanged != null) { PropertyChanged( this, new PropertyChangedEventArgs(p)); } } public event PropertyChangedEventHandler PropertyChanged; } public class OrderLineViewModel : INotifyPropertyChanged { public OrderLineViewModel(OrderLine orderLine) { Label = orderLine.ItemName; double quantity; if (!double.TryParse( orderLine.Quantity, out quantity)) { quantity = 0.0; } Quantity = quantity; } private string _label; public string Label { get { return _label; } set { _label = value; RaisePropertyChanged("Label"); } } private double _quantity; public double Quantity { get { return _quantity; } set { _quantity = value; RaisePropertyChanged("Quantity"); } } private void RaisePropertyChanged(string p) { if (PropertyChanged != null) { PropertyChanged( this, new PropertyChangedEventArgs(p)); } } public event PropertyChangedEventHandler PropertyChanged; } public class OrderLineViewModels : ObservableCollection<OrderLineViewModel> { public OrderLineViewModels( IEnumerable<OrderLine> orderLines) { foreach (OrderLine order in orderLines) { Add(new OrderLineViewModel(order)); } } }
Note: This is only one way of going about getting the data from your database and providing it to XamDataChart.Also note, this code behind would look somewhat simpler if it wasn't dynamically creating a series for each order item.Note: The above code is for the two tables I created in the sample, your code would, of course, be tailored to the data tables you are trying to present in the chart.Hopefully this gives you an idea of one way to approach this kind of project. Hope this helps!-Graham