我正在开发一个执行仪表板,该仪表板应该能够有任意数量的图表,每个图表都有任意数量的系列。我正在使用 WPF 工具包。
我遇到的第一个问题是将多个系列绑定到图表。我发现Beat Kiener 关于将多个系列绑定到图表的出色博客文章效果很好,直到我将其放入项目控件中,我必须这样做才能满足我的“任意数量的图表”要求。
在我看来,下面的代码应该可以工作,但事实并非如此。谁能解释为什么下面的代码不起作用,或者提供另一种使用 MVVM 的方法?
主窗口.xaml.cs
public partial class MainWindow : Window
{
public ChartData ChartData { get; set; }
public List<ChartData> ChartDataList { get; set; }
public MainWindow()
{
var dataSeries = new Dictionary<string, int>();
dataSeries.Add("Jan", 5);
dataSeries.Add("Feb", 7);
dataSeries.Add("Mar", 3);
ChartData = new ChartData();
ChartData.Title = "Chart Title";
ChartData.DataSeriesList = new List<Dictionary<string, int>>();
ChartData.DataSeriesList.Add(dataSeries);
ChartDataList = new List<ChartData>();
ChartDataList.Add(ChartData);
InitializeComponent();
this.DataContext = this;
}
}
public class ChartData
{
public string Title { get; set; }
public List<Dictionary<string, int>> DataSeriesList { get; set; }
}
主窗口.xaml
<UniformGrid
Rows="1">
<!-- These charts do not work -->
<ItemsControl
x:Name="itemsControl"
ItemsSource="{Binding ChartDataList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<local:MultiChart
Title="{Binding Title}"
SeriesSource="{Binding DataSeriesList}">
<local:MultiChart.SeriesTemplate>
<DataTemplate >
<chartingToolkit:ColumnSeries
Title="Series Title"
ItemsSource="{Binding}"
IndependentValueBinding="{Binding Key}"
DependentValueBinding="{Binding Value}"/>
</DataTemplate>
</local:MultiChart.SeriesTemplate>
</local:MultiChart>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- End of not working charts -->
<!-- This chart works -->
<local:MultiChart
Title="{Binding ChartData.Title}"
SeriesSource="{Binding ChartData.DataSeriesList}">
<local:MultiChart.SeriesTemplate>
<DataTemplate>
<chartingToolkit:ColumnSeries
Title="Series Title"
ItemsSource="{Binding}"
IndependentValueBinding="{Binding Key}"
DependentValueBinding="{Binding Value}" />
</DataTemplate>
</local:MultiChart.SeriesTemplate>
</local:MultiChart>
<!-- End of working chart -->
</UniformGrid>
MultiChart.cs
public class MultiChart : System.Windows.Controls.DataVisualization.Charting.Chart
{
#region SeriesSource (DependencyProperty)
public IEnumerable SeriesSource
{
get
{
return (IEnumerable)GetValue(SeriesSourceProperty);
}
set
{
SetValue(SeriesSourceProperty, value);
}
}
public static readonly DependencyProperty SeriesSourceProperty = DependencyProperty.Register(
name: "SeriesSource",
propertyType: typeof(IEnumerable),
ownerType: typeof(MultiChart),
typeMetadata: new PropertyMetadata(
defaultValue: default(IEnumerable),
propertyChangedCallback: new PropertyChangedCallback(OnSeriesSourceChanged)
)
);
private static void OnSeriesSourceChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
IEnumerable oldValue = (IEnumerable)e.OldValue;
IEnumerable newValue = (IEnumerable)e.NewValue;
MultiChart source = (MultiChart)d;
source.OnSeriesSourceChanged(oldValue, newValue);
}
protected virtual void OnSeriesSourceChanged(IEnumerable oldValue, IEnumerable newValue)
{
this.Series.Clear();
if (newValue != null)
{
foreach (object item in newValue)
{
DataTemplate dataTemplate = null;
if (this.SeriesTemplate != null)
{
dataTemplate = this.SeriesTemplate;
}
// load data template content
if (dataTemplate != null)
{
Series series = dataTemplate.LoadContent() as Series;
if (series != null)
{
// set data context
series.DataContext = item;
this.Series.Add(series);
}
}
}
}
}
#endregion
#region SeriesTemplate (DependencyProperty)
public DataTemplate SeriesTemplate
{
get
{
return (DataTemplate)GetValue(SeriesTemplateProperty);
}
set
{
SetValue(SeriesTemplateProperty, value);
}
}
public static readonly DependencyProperty SeriesTemplateProperty = DependencyProperty.Register(
name: "SeriesTemplate",
propertyType: typeof(DataTemplate),
ownerType: typeof(MultiChart),
typeMetadata: new PropertyMetadata(default(DataTemplate))
);
#endregion
}