我有一项服务将返回0或更多组数据。数据结构如下所示:
public class ReportData
{
public List<SeriesSet> SeriesSet {get;set;}
}
public class SeriesSet
{
public DateTime ItemDate {get;set;}
public List<SeriesItem> SeriesItem {get;set;}
}
public class SeriesItem
{
public string ItemType {get;set;}
public double ItemValue {get;set;}
}
我的服务将返回包含SeriesSets列表的ReportData。 SeriesSet数据包含SeriesItems列表。 SeriesSet中的每个SeriesItem必须是我的图表中相应系列中的数据项(即单独的行或条),用于该SeriesSet的特定日期。我想根据服务返回的内容在图表中动态创建系列。
我想我需要首先根据创建系列映射来识别返回的不同ItemType。
我遇到的一个问题是数据来自异步的Web服务。当数据进入我的viewmodel时,如何在视图中使用正确的绑定创建系列映射?
从我创建图表的方式来看,似乎我需要在从视图模型中获取数据之前定义系列映射?
任何指针?
答案 0 :(得分:1)
我最近做了类似的事情。我的SeriesMappings的ItemSources已绑定,但SeriesMappings本身和绑定是在代码隐藏中创建的。
我的视图模型在其数据全部加载时触发了一个事件。视图处理了事件并将新的SeriesMapping对象添加到图表中。以下是创建SeriesMapping对象的一些代码。
void AddBarSeriesMapping(string itemsSourceBindingPath, string legendLabel, string itemFieldName = null)
{
this.AddSeriesMapping(itemsSourceBindingPath, legendLabel, CreateBarSeriesDefinition(), itemFieldName);
}
void AddLineSeriesMapping(string itemsSourceBindingPath, string legendLabel, string itemFieldName = null)
{
this.AddSeriesMapping(itemsSourceBindingPath, legendLabel, CreateLineSeriesDefinition(), itemFieldName);
}
void AddSeriesMapping(string itemsSourceBindingPath, string legendLabel, ISeriesDefinition seriesDefinition, string itemFieldName)
{
//
// Set label and type (bar/line/etc).
//
SeriesMapping seriesMapping = new SeriesMapping
{
ChartArea = this.Chart.DefaultView.ChartArea,
LegendLabel = legendLabel,
SeriesDefinition = seriesDefinition
};
//
// Bind to items source.
//
BindingOperations.SetBinding(seriesMapping, SeriesMapping.ItemsSourceProperty, new Binding(itemsSourceBindingPath));
//
// Map items to the Y value, and set field name if the items source is not a list of numeric values.
//
var itemMapping = new ItemMapping { DataPointMember = DataPointMember.YValue };
if (itemFieldName != null)
{
itemMapping.FieldName = itemFieldName;
}
seriesMapping.ItemMappings.Add(itemMapping);
this.Chart.SeriesMappings.Add(seriesMapping);
}
private static ISeriesDefinition CreateBarSeriesDefinition()
{
return new BarSeriesDefinition
{
ShowItemLabels = false,
ShowItemToolTips = true,
ItemToolTipFormat = "#Y",
InteractivitySettings = DefaultInteractivitySettings
};
}
private static ISeriesDefinition CreateLineSeriesDefinition()
{
return new LineSeriesDefinition
{
ShowItemLabels = false,
ShowItemToolTips = true,
ItemToolTipFormat = "#Y",
InteractivitySettings = DefaultInteractivitySettings
};
}
private static InteractivitySettings DefaultInteractivitySettings;
static ChartSummaryView()
{
DefaultInteractivitySettings = new InteractivitySettings
{
HoverScope = InteractivityScope.Series,
SelectionScope = InteractivityScope.Item
};
}
更新:
为了让视图模型将数据和映射信息传递给视图,也许你可以做这样的事情。
public class SeriesMappingInfo
{
public int DataSourceIndex { get; set; } // Index in ViewModel.DataSources
public string LegendLabel { get; set; }
// Other properties to tell the view how to create the mapping...
}
public class ViewModel
{
public event EventHandler DataLoaded;
public double?[][] DataSources { get; private set; }
public SeriesMappingInfo[] Mappings { get; private set; }
private void OnDataRetrievedFromServer(ReportData data)
{
// TODO: Translate data into something SeriesMappings can bind to, and set DataSources property.
// TODO: Assemble info for creating SeriesMappings, and set Mappings property.
// Tell the view everything is ready.
if (this.DataLoaded != null)
{
this.DataLoaded(this, EventArgs.Empty);
}
}
}
public class View : UserControl
{
public View()
{
this.DataContextChanged += new DependencyPropertyChangedEventHandler(View_DataContextChanged);
// InitializeComponent, etc.
}
private void View_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
{
var viewModel = e.NewValue as ViewModel;
if (viewModel != null)
{
this.CreateSeriesMappings(viewModel.Mappings);
viewModel.DataLoaded += new EventHandler(ViewModel_DataLoaded);
}
}
private void ViewModel_DataLoaded(object sender, EventArgs e)
{
var viewModel = sender as ViewModel;
if (viewModel != null)
{
this.CreateSeriesMappings(viewModel.Mappings);
}
}
private void CreateSeriesMappings(SeriesMappingInfo[] seriesMappingInfo)
{
var chartSeriesMappings = seriesMappingInfo.Select(m =>
{
// TODO: Create mapping. The binding would look something like this:
var seriesMapping = new SeriesMapping();
BindingOperations.SetBinding(seriesMapping, SeriesMapping.ItemsSourceProperty, new Binding(String.Format("DataSources[{0}]", m.DataSourceIndex)));
return seriesMapping;
});
// TODO: Give these mappings to the chart control.
}
}