【发布时间】:2014-05-03 20:53:55
【问题描述】:
我有一个线系列图表的用户控件,并为图表上的项目创建了一堆依赖属性;标题、x 轴标签、数据本身等……数据是 KeyValuePair 的可观察集合。当它在主窗口中时,我的图表工作正常。我的主窗口上必须有 5 个系列图表,所以我认为用户控件将是一个很好的解决方案。我将 xaml 复制并粘贴到一个新的用户控件中。我为我想绑定的所有元素添加了绑定;标题、标签、间隔和数据。然后,我在后面的代码中为所有这些绑定创建了属性,并使用 DependencyProperty.Register 来确保它们会被传递。标题和标签工作得很好,尽管我在主窗口的 xaml 中对它们进行了硬编码。可观察的集合根本没有约束力。我尝试了在这个站点上找到的一堆解决方案(即 - 将 ElementName=NameOfUserControl 添加到绑定,在主窗口的绑定上添加 RelativeSource=UserControl)。我似乎无法让这些数据通过。
如果我不在主窗口中添加 RelativeSource 子句,我会收到此错误:
System.Windows.Data 错误:40:BindingExpression 路径错误:在“对象”“LineGraph”(名称=“我”)上找不到“处置”属性。 BindingExpression:Path=Disposition.WidthData; > DataItem='LineGraph'(名称='我');目标元素是'LineGraph'(名称='Me'); target > 属性是 'ActualData'(类型 'ObservableCollection`1')
我之前遇到过这个问题,最终我放弃了,只是将 xaml 直接放入我的主窗口,而不是使用用户控件。我想弄清楚这一点,以便我可以使用更多用户控件,并且我的主窗口中没有 1000 行 xaml。
这是用户控件 xaml:
<UserControl x:Class="Essar.Dispo.UI.UserControls.LineGraph"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:toolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
xmlns:datavis="clr-namespace:System.Windows.Controls.DataVisualization;assembly=System.Windows.Controls.DataVisualization.Toolkit"
mc:Ignorable="d" x:Name="Me"
>
<UserControl.Resources>
<Style TargetType="datavis:Title" x:Key="GraphTitleStyle">
<Setter Property="Foreground" Value="Black" />
<Setter Property="HorizontalAlignment" Value="Center" />
<Setter Property="FontSize" Value="16" />
<Setter Property="FontWeight" Value="Bold" />
</Style>
<Style TargetType="datavis:Title" x:Key="AxisTitleStyle" BasedOn="{StaticResource GraphTitleStyle}">
<Setter Property="FontSize" Value="12" />
<Setter Property="FontWeight" Value="Medium" />
</Style>
<Style TargetType="datavis:Legend" x:Key="LegendStyle">
<Setter Property="Width" Value="0" />
</Style>
<Style TargetType="toolkit:AxisLabel" x:Key="AxisLabelStyle">
<Setter Property="Foreground" Value="Black" />
</Style>
</UserControl.Resources>
<Grid>
<toolkit:Chart Name="FinishingMillWidthChart" Title="{Binding MainTitle}" Height="350"
TitleStyle="{StaticResource GraphTitleStyle}"
LegendStyle="{StaticResource LegendStyle}">
<toolkit:Chart.Axes>
<toolkit:LinearAxis Orientation="X" Title="{Binding XAxisTitle}" Interval="{Binding XAxisInterval}" ShowGridLines="True"
AxisLabelStyle="{StaticResource AxisLabelStyle}" TitleStyle="{StaticResource AxisTitleStyle}" />
<toolkit:LinearAxis Orientation="Y" Title="{Binding YAxisTitle}" ShowGridLines="True" Interval="{Binding YAxisInterval}"
AxisLabelStyle="{StaticResource AxisLabelStyle}" TitleStyle="{StaticResource AxisTitleStyle}" />
</toolkit:Chart.Axes>
<toolkit:LineSeries Title="tolerance high" DependentValuePath="Value" IndependentValuePath="Key"
ItemsSource="{Binding ToleranceHigh, ElementName=Me}" Visibility="{Binding HighLowVisible}">
<toolkit:LineSeries.DataPointStyle>
<Style TargetType="{x:Type toolkit:DataPoint}">
<Setter Property="Template" Value="{x:Null}" />
<Setter Property="Background" Value="YellowGreen" />
</Style>
</toolkit:LineSeries.DataPointStyle>
</toolkit:LineSeries>
<toolkit:LineSeries Title="actual" DependentValuePath="Value" IndependentValuePath="Key"
ItemsSource="{Binding ActualData, ElementName=Me}">
<toolkit:LineSeries.DataPointStyle>
<Style TargetType="{x:Type toolkit:DataPoint}">
<Setter Property="Template" Value="{x:Null}" />
<Setter Property="Background" Value="Maroon" />
</Style>
</toolkit:LineSeries.DataPointStyle>
</toolkit:LineSeries>
<toolkit:LineSeries Title="tolerance low" DependentValuePath="Value" IndependentValuePath="Key"
ItemsSource="{Binding ToleranceLow, ElementName=Me}" Visibility="{Binding HighLowVisible}">
<toolkit:LineSeries.DataPointStyle>
<Style TargetType="{x:Type toolkit:DataPoint}">
<Setter Property="Template" Value="{x:Null}" />
<Setter Property="Background" Value="DarkCyan" />
</Style>
</toolkit:LineSeries.DataPointStyle>
</toolkit:LineSeries>
</toolkit:Chart>
</Grid>
下面是用户控件的代码:
public partial class LineGraph : UserControl
{
public LineGraph()
{
InitializeComponent();
DataContext = this;
}
#region Properties
public static readonly DependencyProperty MainTitleProperty = DependencyProperty.Register("MainTitle", typeof(string), typeof(LineGraph));
public string MainTitle
{
get { return GetValue(MainTitleProperty).ToString(); }
set { SetValue(MainTitleProperty, value); }
}
public static readonly DependencyProperty XAxisTitleProperty = DependencyProperty.Register("XAxisTitle", typeof(string), typeof(LineGraph));
public string XAxisTitle
{
get { return GetValue(XAxisTitleProperty).ToString(); }
set { SetValue(XAxisTitleProperty, value); }
}
public static readonly DependencyProperty YAxisTitleProperty = DependencyProperty.Register("YAxisTitle", typeof(string), typeof(LineGraph));
public string YAxisTitle
{
get { return GetValue(YAxisTitleProperty).ToString(); }
set { SetValue(YAxisTitleProperty, value); }
}
public static readonly DependencyProperty XAxisIntervalProperty = DependencyProperty.Register("XAxisInterval", typeof(double), typeof(LineGraph));
public double XAxisInterval
{
get { return Common.DoubleParse(GetValue(XAxisIntervalProperty)); }
set { SetValue(XAxisIntervalProperty, value); }
}
public static readonly DependencyProperty YAxisIntervalProperty = DependencyProperty.Register("YAxisInterval", typeof(double), typeof(LineGraph));
public double YAxisInterval
{
get { return Common.DoubleParse(GetValue(YAxisIntervalProperty)); }
set { SetValue(YAxisIntervalProperty, value); }
}
public static readonly DependencyProperty ToleranceHighProperty = DependencyProperty.Register("ToleranceHigh", typeof(ObservableCollection<KeyValuePair<double, double>>), typeof(LineGraph));
public ObservableCollection<KeyValuePair<double, double>> ToleranceHigh
{
get
{
return GetValue(ToleranceHighProperty) as ObservableCollection<KeyValuePair<double, double>>;
}
set { SetValue(ToleranceHighProperty, value); }
}
public static readonly DependencyProperty ActualDataProperty = DependencyProperty.Register("ActualData", typeof(ObservableCollection<KeyValuePair<double, double>>), typeof(LineGraph));
public ObservableCollection<KeyValuePair<double, double>> ActualData
{
get
{
return GetValue(ActualDataProperty) as ObservableCollection<KeyValuePair<double, double>>;
}
set { SetValue(ActualDataProperty, value); }
}
public static readonly DependencyProperty ToleranceLowProperty = DependencyProperty.Register("ToleranceLow", typeof(ObservableCollection<KeyValuePair<double, double>>), typeof(LineGraph));
public ObservableCollection<KeyValuePair<double, double>> ToleranceLow
{
get
{
return GetValue(ToleranceLowProperty) as ObservableCollection<KeyValuePair<double, double>>;
}
set { SetValue(ToleranceLowProperty, value); }
}
public Visibility HighLowVisible
{
get
{
if (ToleranceHigh == null || ToleranceLow == null)
return Visibility.Hidden;
return Visibility.Visible;
}
}
#endregion
}
请注意,Common.DoubleParse 是我的框架中的一个函数,它执行 double.TryParse,真的没什么特别的。
最后这是我主窗口中的 xaml,不确定这是否重要,但图表位于 tabitem、scrollviewer 和停靠面板中。
<uc:LineGraph MainTitle="finishing mill width" Margin="5"
XAxisTitle="length (meters)" XAxisInterval="10"
YAxisTitle="millimeters" YAxisInterval="15"
ToleranceHigh="{Binding Disposition.WidthToleranceHigh}"
ActualData="{Binding Disposition.WidthData}"
ToleranceLow="{Binding Disposition.WidthToleranceLow}"/>
另一个注意事项,我的 MainWindowViewModel 有一个名为 Disposition 的属性,它是另一个具有自己属性的视图模型。请记住,当图表位于完全相同的位置但完整写出时,它工作得很好。我在想我在主窗口或用户控件中的绑定缺少一些愚蠢的东西。
任何帮助表示赞赏:-)
【问题讨论】:
标签: wpf mvvm user-controls observablecollection dependency-properties