Visualizing data is a common need for users. Data can be visualized in different forms, like in a table/grid form or a graphical representation, for example. ComponentOne FlexGrid is used to visualize data in table/grid form, and FlexChart is a graphical representation of data. FlexGrid and FlexChart can be synchronously connected to the data to see dynamic updates on any change in data.
This blog will show how to connect a FlexChart to a FlexGrid to create a bound MVVM (Model-View-ViewModel) scenario similar to Microsoft Excel. Users can add, delete and modify items in FlexGrid, which will reflect in FlexChart.
Steps to Create a Dynamic WPF Chart
Create the Model and ViewModel
Create a model class according to the data and implement the INotifyPropertyChanged interface to notify when a property value changes. This is the key step so that when data changes by FlexGrid, the View (which also contains FlexChart) will be notified.
public class Country : INotifyPropertyChanged
{
private string _name;
public string Name
{
get { return _name; }
set { _name = value; OnPropertyRaised("Name"); }
}
private int _sales;
public int Sales
{
get { return _sales; }
set { _sales = value; OnPropertyRaised("Sales"); }
}
private int _downloads;
public int Downloads
{
get { return _downloads; }
set { _downloads = value; OnPropertyRaised("Downloads"); }
}
public event PropertyChangedEventHandler PropertyChanged;
public void OnPropertyRaised(string property)
{
if(PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
Now, create a ViewModel named DataViewModel, which will connect to the View. We can create some properties and methods in ViewModel which can be bound to the view.
public class DataViewModel
{
private ObservableCollection<Country> _countries;
public ObservableCollection<Country> Countries
{
get { return _countries; }
set { _countries = value; }
}
private string _desc;
public string Desc
{
get { return _desc; }
set { _desc = value; }
}
/// <summary>
/// C'tor
/// </summary>
public DataViewModel()
{
//create a dummy data
var country = new string[] { "China", "India", "Japan", "US" };
var count = country.Length;
Countries = new ObservableCollection<Country>();
var rnd = new Random();
for (var i = 0; i < count; i++)
Countries.Add(new Country()
{
Name = country[i],
Sales = 1 + rnd.Next(100,1000),
Downloads = 1 + rnd.Next(100, 1000),
});
Desc = "You can modify, add or delete Flexgrid's item and this will reflect on FlexChart.";
}
}
Create the View
Now, it’s time to create a User Interface(View). Add C1FlexChart and C1FlexGrid to the view, bound their ItemsSources and respective properties.
<Window
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"
xmlns:local="clr-namespace:DynamicFlexChart"
xmlns:c1="http://schemas.componentone.com/winfx/2006/xaml" x:Class="DynamicFlexChart.MainWindow"
xmlns:vm ="clr-namespace:DynamicFlexChart.ViewModel"
mc:Ignorable="d"
Title="Dynamic FlexChart" Height="450" Width="800">
<Window.DataContext>
<vm:DataViewModel/>
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="40"/>
<RowDefinition/>
</Grid.RowDefinitions>
<TextBlock x:Name="desc" Text="{Binding Desc}" FontSize="14" TextWrapping="Wrap" Margin="10,0,0,0"/>
<Grid Grid.Row="1">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<!-- FlexGrid -->
<c1:C1FlexGrid x:Name="flexGrid" ItemsSource="{Binding Countries}" AllowAddNew="True" KeyDown="Key_Down" AutoGenerateColumns="False">
<c1:C1FlexGrid.Columns>
<c1:Column Header="Name" Binding="{Binding Name}"/>
<c1:Column Header="Sales" Binding="{Binding Sales}"/>
<c1:Column Header="Downloads" Binding="{Binding Downloads}"/>
</c1:C1FlexGrid.Columns>
</c1:C1FlexGrid>
<!-- FlexChart -->
<c1:C1FlexChart x:Name="flexChart" Grid.Column="1" ItemsSource="{Binding Countries}" BindingX="Name" LegendPosition="Bottom">
<c1:C1FlexChart.Series>
<c1:Series Binding="Sales" SeriesName="Sales"/>
<c1:Series Binding="Downloads" SeriesName="Downloads"/>
</c1:C1FlexChart.Series>
<c1:C1FlexChart.DataLabel>
<c1:DataLabel Content=" {value}" Position="Top"/>
</c1:C1FlexChart.DataLabel>
</c1:C1FlexChart>
</Grid>
</Grid>
</Window>
And it’s done. Now you can edit, add or remove data from Flexgrid, which will dynamically update to the FlexChart.
For full implementation, you can download the sample.