我有一个Series
属性SeriesCollection
的图表控件,它继承ObservableCollection<Series>
。 Series
的{{1}}属性Values
继承ChartValues
。当我将ObservableCollection<double>
添加到Series
中的SeriesCollection
时Xaml
绑定由于某种原因无法正常工作,Values
永远不会被调用。
但是,如果我将OnValuesChanged()
移到Series
之外,则会调用SeriesCollection
。
Chart.cs
OnValuesChanged()
SeriesCollection.cs
public class Chart : Control
{
public static readonly DependencyProperty SeriesProperty =
DependencyProperty.Register(nameof(Series), typeof(SeriesCollection), typeof(Chart),
new PropertyMetadata(default(SeriesCollection),
(s, e) => (s as Chart)?.OnSeriesChanged()));
private Canvas _canvas;
public Chart()
{
DefaultStyleKey = typeof(Chart);
}
public SeriesCollection Series
{
get => (SeriesCollection) GetValue(SeriesProperty);
set => SetValue(SeriesProperty, value);
}
public List<ChartGroup> Groups { get; private set; }
private void SortChartGroups()
{
Groups = new List<ChartGroup>();
var max = Series.Select(s => s.Values?.Count).Max();
if (max > 0)
{
for (var i = 0; i < max; i++)
{
var points = Series.SelectMany(s => s.ChartPoints).Where(c => c.Index == i).ToList();
Groups.Add(new ChartGroup
{
Index = i,
Values = points
});
}
}
}
public void OnCollectionChanged()
{
Update();
}
private void OnSeriesChanged()
{
Series.CollectionChanged += (s, e) =>
{
OnCollectionChanged();
};
OnCollectionChanged();
}
protected virtual void Update()
{
if (Series.Count > 0)
{
SortChartGroups();
if (Groups.Count > 0)
{
var count = Series.Count;
var values = Groups.SelectMany(g => g.Values.Select(p => p.Value)).ToList();
var min = values.Min();
var max = values.Max();
// Draw here
// Calculate drawing region
Draw();
}
}
}
public override void OnApplyTemplate()
{
base.OnApplyTemplate();
_canvas = GetTemplateChild("PART_Canvas") as Canvas;
Loaded += (s, e) => Draw();
SizeChanged += (s, e) => Draw();
}
private void Draw()
{
if (!IsLoaded || Series == null) return;
//_canvas.Children.Clear();
}
}
Series.cs
public class SeriesCollection : ObservableCollection<Series>
{
}
ChartValues.cs
public class Series : DependencyObject
{
public static readonly DependencyProperty ValuesProperty =
DependencyProperty.Register(nameof(Values), typeof(ChartValues), typeof(Series),
new PropertyMetadata(default(ChartValues),
(s, e) => (s as Series)?.OnValuesChanged()));
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register(
nameof(Title), typeof(string), typeof(Series), new PropertyMetadata(default(string)));
public static readonly DependencyProperty ColorProperty = DependencyProperty.Register(
nameof(Color), typeof(Color), typeof(Series), new PropertyMetadata(default(Color)));
internal Chart Chart { private get; set; }
public string Title
{
get => (string) GetValue(TitleProperty);
set => SetValue(TitleProperty, value);
}
public Color Color
{
get => (Color) GetValue(ColorProperty);
set => SetValue(ColorProperty, value);
}
public ChartValues Values
{
get => (ChartValues) GetValue(ValuesProperty);
set => SetValue(ValuesProperty, value);
}
internal List<ChartPoint> ChartPoints { get; private set; }
private void OnCollectionChanged()
{
ChartPoints = new List<ChartPoint>();
for (var i = 0; i < Values.Count; i++)
{
ChartPoints.Add(new ChartPoint
{
Title = Title,
Value = Values[i],
Index = i
});
}
Chart?.OnCollectionChanged();
}
private void OnValuesChanged()
{
if (Values != null)
{
Values.CollectionChanged += (s, e) =>
{
OnCollectionChanged();
};
OnCollectionChanged();
}
}
}
的Xaml
如果我将public class ChartValues : ObservableCollection<double>
{
}
移到Series
之外,SeriesCollection
被调用
OnValuesChanged()
但是,当置于<charts:Series Values="{Binding SomeValues}"/>
<charts:Series Values="{Binding OtherValues}" />
内时,对值的绑定不起作用,该类已初始化,但值属性永远不会被绑定设置,而SeriesCollection
从未被调用。调用OnValuesChanged()
Chart
并且OnSeriesChanged()
属性中有2个项目,但Series
上的绑定永远不会有效。
Values
我绑定到这些值的原因是我在<charts:Chart>
<charts:Chart.Series>
<charts:SeriesCollection>
<charts:Series Values="{Binding SomeValues}"/>
<charts:Series Values="{Binding OtherValues}" />
</charts:SeriesCollection>
</charts:Chart.Series>
</charts:Chart>
课程中有其他属性,我在Series
中设置了我并不真正想要的包含在视图模型中,例如标题和颜色
我已查看过这篇文章Initialize Collection of DataTemplates in XAML的答案,但它似乎无法解决我遇到的问题。
修改
我尝试绑定到用户控件的xaml
,但无法找到DataContext
。它似乎不是视觉树的一部分?
UserControl
修改
Chart.xaml
<charts:Series Values="{Binding Path=DataContext.SomeValues, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"/>
Generic.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:charts="<omitted>.Charts">
<Style TargetType="{x:Type charts:Chart}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type charts:Chart}">
<Grid>
<ItemsControl ItemsSource="{TemplateBinding Series}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type charts:Series}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type charts:Series}">
<Grid>
<ListBox ItemsSource="{TemplateBinding Values}"/>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
的App.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/<omitted>;component/Themes/Chart.xaml" />
</ResourceDictionary.MergedDictionaries>