带有ObservableCollection的WPF UserControl DependencyProperty没有绑定

时间:2014-03-25 19:20:21

标签: wpf mvvm user-controls observablecollection dependency-properties

我有一个Line Series Chart的用户控件,并为图表上的项创建了一堆依赖属性;标题,x轴标签,数据本身等......数据是KeyValuePair的可观察集合。当它在主窗口中时,我的图表工作正常。我必须在主窗口上有5个系列图表,所以我认为用户控件是一个很好的解决方案。我将xaml复制并粘贴到新的用户控件中。我添加了绑定到我想要绑定的所有元素;标题,标签,间隔和数据。然后我在后面的代码中为所有这个绑定创建了属性,并使用DependencyProperty.Register来确保它们将被传递。标题和标签工作得很好,虽然我在主窗口的xaml中硬编码。可观察的集合根本没有约束力。我尝试了在这个网站上找到的一堆解决方案(即 - 将ElementName = NameOfUserControl添加到绑定,在主窗口的绑定上添加RelativeSource = UserControl)。我似乎无法通过这些数据。

如果我没有在主窗口中添加RelativeSource子句,我会收到此错误:

  

System.Windows.Data错误:40:BindingExpression路径错误:'处置'属性不是>找到'object'''LineGraph'(Name ='Me')'。 BindingExpression:路径= Disposition.WidthData; > DataItem ='LineGraph'(Name ='Me'); target元素是'LineGraph'(Name ='Me');目标> property是'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和dockpanel内。

<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的属性,它是另一个具有自己属性的视图模型。请记住,当图表位于这个完全相同的位置但完整写出时,它可以完美地工作。我想我在主窗口或用户控件中缺少一些愚蠢的东西。

感谢任何帮助: - )

1 个答案:

答案 0 :(得分:0)

永远不要将usercontrol的datacontext设置为此!所以只需删除您的线路。

public LineGraph()
{
    InitializeComponent();
}

现在当然你应该为你的所有绑定添加你的元素名称,例如

        <toolkit:LinearAxis Orientation="X" 
             Title="{Binding XAxisTitle, ElementName=Me}" 
             Interval="{Binding XAxisInterval, ElementName=Me}" 
             ShowGridLines="True" AxisLabelStyle="{StaticResource AxisLabelStyle}" TitleStyle="{StaticResource AxisTitleStyle}" />
编辑:你能不能尝试一下这段代码,看看你对收藏品的约束是否合适?

<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"
     >
<Grid>
<ItemsControl ItemsSource="{Binding Path=ActualData, ElementName=Me}"/>
</Grid>

并在主视图中添加以下内容

<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}"/>
<ItemsControl ItemsSource="{Binding Disposition.WidthData}"/>

两个itemscontrols都应该显示相同的内容。

然后您可以在运行时使用SNOOP

检查绑定