我有一个ItemsControl,它绑定到一个可观察的集合。在控件ItemTemplate中,我有一个Canvas,它包含一个我用来绘制一些线段的路径。像这样:
<ItemsControl
ItemsSource="{Binding CombinedPieChartData}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Canvas>
<Path Stroke="Black" StrokeThickness="1" Fill="{Binding Color}">
<Path.Data>
<GeometryGroup>
<PathGeometry>
<PathFigure StartPoint="{Binding FirstPoint1}">
<PathFigure.Segments>
<LineSegment Point="{Binding SecondPoint1}"/>
</PathFigure.Segments>
</PathFigure>
</PathGeometry>
</GeometryGroup>
</Path.Data>
</Path>
</Canvas>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
将Path的Fill属性绑定到Color属性效果良好。但是,绑定到PathFigure的起点和线段点不起作用。它显示正确,但报告这些错误:
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=FirstPoint1; DataItem='PieChartDataPoint' (HashCode=35164785); target element is 'PathFigure' (HashCode=9043297); target property is 'StartPoint' (type 'Point')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=SecondPoint1; DataItem='PieChartDataPoint' (HashCode=35164785); target element is 'LineSegment' (HashCode=52141992); target property is 'Point' (type 'Point')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=FirstPoint1; DataItem='PieChartDataPoint' (HashCode=52449849); target element is 'PathFigure' (HashCode=8195173); target property is 'StartPoint' (type 'Point')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=SecondPoint1; DataItem='PieChartDataPoint' (HashCode=52449849); target element is 'LineSegment' (HashCode=41799477); target property is 'Point' (type 'Point')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=FirstPoint1; DataItem='PieChartDataPoint' (HashCode=15121425); target element is 'PathFigure' (HashCode=46419306); target property is 'StartPoint' (type 'Point')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=SecondPoint1; DataItem='PieChartDataPoint' (HashCode=15121425); target element is 'LineSegment' (HashCode=50982559); target property is 'Point' (type 'Point')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=FirstPoint1; DataItem=null; target element is 'PathFigure' (HashCode=61646970); target property is 'StartPoint' (type 'Point')
System.Windows.Data Error: 2 : Cannot find governing FrameworkElement or FrameworkContentElement for target element. BindingExpression:Path=SecondPoint1; DataItem=null; target element is 'LineSegment' (HashCode=38860075); target property is 'Point' (type 'Point')
我真的很困惑为什么会出现这些错误,无法在网上找到任何帮助。有什么建议吗?
这是我在Observable集合中使用的类
public class PieChartDataPoint : ObservableObject
{
public string Catagory { get; set; }
public double Value { get; set; }
public SolidColorBrush Color { get; set; }
private Point firstPoint1;
public Point FirstPoint1
{
get
{
return firstPoint1;
}
set
{
firstPoint1 = value;
RaisePropertyChangedEvent("FirstPoint1");
}
}
private Point secondPoint1;
public Point SecondPoint1
{
get
{
return secondPoint1;
}
set
{
secondPoint1 = value;
RaisePropertyChangedEvent("SecondPoint1");
}
}
private Size pieSize;
public Size PieSize
{
get
{
return pieSize;
}
set
{
pieSize = value;
RaisePropertyChangedEvent("PieSize");
}
}
private int colorIndex = 0;
public int ColorIndex
{
get { return colorIndex; }
set
{
colorIndex = value;
Color newColor = Utilities.SelectColour(value);
newColor.A = 190;
this.Color = new SolidColorBrush(newColor);
}
}
public double Fraction { get; set; }
public string Percentage
{
get
{
return String.Format("{0:P2}", Fraction);
}
}
public PieChartDataPoint(string Catagory, double Value, int ColorIndex, double Fraction)
{
this.Catagory = Catagory;
this.Value = Value;
this.ColorIndex = ColorIndex;
this.Fraction = Fraction;
}
}
因此,在xaml中设置Path的Data属性。此属性的类型为Geometry,它不是视觉树的一部分(几何体本身不是视觉控件,它用于渲染路径)。这意味着:它不继承"父"DataContext,因为它实际上不在可视化树中,也没有父(这比这更复杂,因为一些非可视化的元素确实继承了DataContext,但在这种情况下不是)。
您可以在DataTemplate中创建"fake"元素,该元素将继承父DataContext,然后将其用作绑定的源。任何"假"元素都不会起作用,请参阅本文:http://www.thomaslevesque.com/2011/03/21/wpf-how-to-bind-to-data-when-the-datacontext-is-not-inherited/
现在,从该文章中复制BindingProxy类,然后:
<ItemsControl
ItemsSource="{Binding CombinedPieChartData}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<Canvas/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<Canvas>
<Canvas.Resources>
<local:BindingProxy x:Key="proxy" Data="{Binding}" />
</Canvas.Resources>
<Path Stroke="Black" StrokeThickness="1" Fill="{Binding Color}">
<Path.Data>
<GeometryGroup>
<PathGeometry>
<PathFigure StartPoint="{Binding Source={StaticResource proxy}, Path=Data.FirstPoint1}">
<PathFigure.Segments>
<LineSegment Point="{Binding Source={StaticResource proxy}, Path=Data.SecondPoint1}"/>
</PathFigure.Segments>
</PathFigure>
</PathGeometry>
</GeometryGroup>
</Path.Data>
</Path>
</Canvas>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
您所做的是在可视化元素的资源中创建"代理"控件,该控件以特殊方式构建(继承自Freezable-请参阅上面的文章),并且,尽管不是可视化树的一部分,但将继承父DataContext。然后,您只需使用该代理作为绑定的源。