【问题标题】:WPF Binding with Dependency Properties. Issue with Data Not Displaying具有依赖属性的 WPF 绑定。数据不显示的问题
【发布时间】:2014-06-23 18:34:01
【问题描述】:

我整个上午都在尝试让它工作,但没有运气。我正在使用 DynamicDataDisplay (D3) 来显示图表。这是我使用 xaml 定义的简单视图。

<Window x:Class="BMSVM_Simulator.View.GraphWindowView"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:ViewModel="clr-namespace:BMSVM_Simulator.ViewModel"
        xmlns:d3="http://research.microsoft.com/DynamicDataDisplay/1.0"
        x:Name="ThisGraphWindowInstance"
        Title="Plot" Height="500" Width="750"
        WindowStartupLocation="CenterOwner"
        Icon="../res/qualcomm_q_icon.ico.ico"
        MinWidth="400" MinHeight="300">

    <Window.DataContext>
        <ViewModel:GraphWindowPresenter/>
    </Window.DataContext>

    <Grid>
        <d3:ChartPlotter Name="plotter" Margin="10,10,20,10">
            <d3:InjectedPlotter Name="innerPlotter" Background="Aqua" SetViewportBinding="False">
                <d3:VerticalAxis Placement="Right"/>
                <d3:VerticalAxisTitle Content="{Binding ElementName=ThisGraphWindowInstance, Path=yAxis2}" Placement="Right"/>
            </d3:InjectedPlotter>      

            <d3:Header FontFamily="Arial" Content="{Binding ElementName=ThisGraphWindowInstance, Path=title}"/>
            <d3:VerticalAxisTitle FontFamily="Arial" Content="{Binding ElementName=ThisGraphWindowInstance, Path=yAxis2}"/>
            <d3:HorizontalAxisTitle FontFamily="Arial" Content="{Binding ElementName=ThisGraphWindowInstance, Path=title}"/>
        </d3:ChartPlotter>
    </Grid>
</Window>

问题在于:

<d3:VerticalAxisTitle Content="{Binding ElementName=ThisGraphWindowInstance, Path=yAxis2}" Placement="Right"/>

当我使用当前设置并将Content 绑定到Path=yAxis2 时,InjectedPlotter 中根本不显示。我在断点处设置,我看到yAxis2 实际上是一个已定义的字符串并且它不为空。

当我实际硬编码一个值,例如Content="DEFAULT TITLE",那么它就变成了:

<d3:VerticalAxisTitle Content="DEFAULT TITLE" Placement="Right"/>

标题显示正常。

有人知道为什么会这样吗?

后面的代码供参考:

public static readonly DependencyProperty yAxis2Property =
    DependencyProperty.Register("yAxis2", typeof(string), typeof(GraphWindowView));

public string yAxis2
{
    get { return (string)GetValue(yAxis2Property); }
    set { SetValue(yAxis2Property, value); }
}

public void ShowGraph()
{
    // consume ChartData
    this.yAxis1 = ChartData.yAxisTitle1;
    this.yAxis2 = "AXIS 2 TITLE..SHOW UP!";
     .....
}

编辑>>>>>>>>>

using BMSVM_Simulator.ViewModel;
using Microsoft.Research.DynamicDataDisplay;
using Microsoft.Research.DynamicDataDisplay.DataSources;
using Microsoft.Research.DynamicDataDisplay.Navigation;
using Microsoft.Research.DynamicDataDisplay.PointMarkers;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Shapes;

namespace BMSVM_Simulator.View
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class GraphWindowView : Window
    {
        #region Fields

        private readonly int DEFAULT_AXIS_WIDTH = 20;

        private readonly Pen[] colors = {   
                                            new Pen(Brushes.Blue, 2),
                                            new Pen(Brushes.DarkGreen, 2),
                                            new Pen(Brushes.DarkMagenta, 2),
                                            new Pen(Brushes.DarkSalmon, 2),
                                            new Pen(Brushes.Maroon, 2),
                                            new Pen(Brushes.Orange, 2),
                                            new Pen(Brushes.SkyBlue, 2)
                                        };

        #endregion

        #region DependencyProperties

        public static readonly DependencyProperty yAxis1Property =
            DependencyProperty.Register("yAxis1", typeof(string), typeof(GraphWindowView));

        public static readonly DependencyProperty yAxis2Property =
            DependencyProperty.Register("yAxis2", typeof(string), typeof(GraphWindowView));

        public static readonly DependencyProperty titleProperty =
            DependencyProperty.Register("title", typeof(string), typeof(GraphWindowView));

        public static readonly DependencyProperty xAxisProperty =
            DependencyProperty.Register("xAxis", typeof(string), typeof(GraphWindowView));

        public static readonly DependencyProperty DatesProperty =
            DependencyProperty.Register("Dates", typeof(EnumerableDataSource<int>), typeof(GraphWindowView));

        public static readonly DependencyProperty DataProperty =
            DependencyProperty.Register("Data", typeof(EnumerableDataSource<int>), typeof(GraphWindowView));

        public static readonly DependencyProperty ChartDataProperty =
            DependencyProperty.Register("ChartData", typeof(ChartData), typeof(GraphWindowView));

        public static readonly DependencyProperty rightAxisWidthProperty =
            DependencyProperty.Register("rightAxisWidth", typeof(int), typeof(GraphWindowView));

        public int rightAxisWidth
        {
            get { return (int)GetValue(rightAxisWidthProperty); }
            set { SetValue(rightAxisWidthProperty, value); }
        }

        public ChartData ChartData
        {
            get { return (ChartData)GetValue(ChartDataProperty); }
            set { SetValue(ChartDataProperty, value); }
        }

        public EnumerableDataSource<int> Dates
        {
            get { return (EnumerableDataSource<int>)GetValue(DatesProperty); }
            set { SetValue(DatesProperty, value); }
        }

        public EnumerableDataSource<int> Data
        {
            get { return (EnumerableDataSource<int>)GetValue(DataProperty); }
            set { SetValue(DataProperty, value); }
        }

        public string xAxis
        {
            get { return (string)GetValue(xAxisProperty); }
            set { SetValue(xAxisProperty, value); }
        }

        public string yAxis1
        {
            get { return (string)GetValue(yAxis1Property); }
            set { SetValue(yAxis1Property, value); }
        }

        public string title
        {
            get { return (string)GetValue(titleProperty); }
            set { SetValue(titleProperty, value); }
        }

        public string yAxis2
        {
            get { return (string)GetValue(yAxis2Property); }
            set { SetValue(yAxis2Property, value); }
        }

        #endregion

        public GraphWindowView()
        {
            InitializeComponent();
            rightAxisWidth = DEFAULT_AXIS_WIDTH;
        }

        public void ShowGraph()
        {
            // consume ChartData
            this.xAxis = ChartData.xAxisTitle;
            this.yAxis1 = ChartData.yAxisTitle1;
            this.yAxis2 = "AXIS 2 TITLE..SHOW UP!"; // ChartData.yAxisTitle2;
            this.title = ChartData.title;
            this.rightAxisWidth = DEFAULT_AXIS_WIDTH;

            // list of data points
            List<DataSet> dataSets = this.ChartData.dataPoints;

            int colorCounter = 0;
            int rightAxisCount = 0;
            foreach (DataSet set in dataSets)
            {

                set.dates.SetXMapping(x => x);
                set.data.SetYMapping(x => x);

                CompositeDataSource compositeDataSource1 = new
                    CompositeDataSource(set.dates, set.data);

                if (set.axis == AxisSide.LEFT)
                {
                    plotter.AddLineGraph(compositeDataSource1, colors[colorCounter % colors.Length],
                    new CirclePointMarker { Size = 8.00, Fill = Brushes.Red },
                    new PenDescription(set.legendTitle));
                }
                else
                {
                    innerPlotter.AddLineGraph(compositeDataSource1, colors[colorCounter % colors.Length],
                    new CirclePointMarker { Size = 8.00, Fill = Brushes.Red },
                    new PenDescription(set.legendTitle));

                    rightAxisCount++;
                }


                colorCounter++;
            }

            // if there is nothing plotted against the right axis, don't show it
            if (rightAxisCount == 0)
            {
                rightAxisWidth = 0;
            }

            plotter.Viewport.FitToView();

            // there are duplicate legends, so we hide one
            plotter.LegendVisibility = Visibility.Hidden;

            Show();
        }
    }
}

【问题讨论】:

    标签: c# wpf xaml dynamic-data-display


    【解决方案1】:

    在您提供的代码中,您已将 datacontext 设置为 GraphWindowPresenter 的对象,但在声明依赖属性时您已设置 GraphWindowView 对象。请确保将适当的对象设置为 datacontext

        <Window.DataContext>
           < ViewModel:GraphWindowPresenter/>
      < /Window.DataContext>
    

    DependencyProperty.Register("yAxis2", typeof(string), typeof(GraphWindowView))

    【讨论】:

    • 我也在想同样的事情。实际上,我将GraphWindowPresenter 设置为数据上下文,但我没有使用该类中的任何内容。我想我可以把它评论出来,它不会有任何效果。我在我展示的 .xaml 后面的代码中严格绑定到事物。与此有关的东西会导致问题吗?我不这么认为,因为我也以相同的方式在后面的代码中绑定到其他 DP,并且它们工作正常。此外,在调试器中,我很肯定值正在设置,因为它显示在调试器中。
    • 您好,您已经设置了正确的数据上下文。 Datacontext 是 xaml 中的控件将通过它绑定到属性的对象。为了更好地理解,请通过链接msdn.microsoft.com/en-us/library/ms752914(v=vs.110).aspx
    • 是的,我知道这是控制 xaml 的对象。不过,从我读过的所有内容来看,这似乎应该有效。有什么问题吗?
    • 是的,问题是您没有为您的视图提供确切的数据上下文。在此处粘贴 datacontext 设置代码
    • 除了&lt;DataContext&gt; 标签之外,我没有设置任何数据上下文。这是完整的代码隐藏(我将其添加到原始帖子中)。
    【解决方案2】:

    试试:

          <d3:VerticalAxisTitle Content="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=yAxis2,Mode=OneWay}" />
    

    【讨论】:

    • 不,它仍然在调试器中将它识别为正确的字符串,但它不会显示。嗯..
    【解决方案3】:

    我运行了一个绑定TextBox.Text 的快速测试,并且您发布的代码有效。

    <Window x:Class="WpfApplication2.MainWindow"
            x:Name="TestWindow" ...>
        <StackPanel>
            <!-- both bindings work -->
            <TextBlock Text="{Binding ElementName=TestWindow, Path=yAxis2}" />
            <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type local:MainWindow}}, Path=yAxis2}" />
        </StackPanel>
    </Window>
    
    public partial class MainWindow : Window
    {
        public static readonly DependencyProperty yAxis2Property =
            DependencyProperty.Register("yAxis2", typeof(string), typeof(MainWindow));
    
        public string yAxis2
        {
            get { return (string)GetValue(yAxis2Property); }
            set { SetValue(yAxis2Property, value); }
        }
    
        public MainWindow()
        {
            InitializeComponent();
            this.yAxis2 = "TESTING";
        }
    

    }

    所以我最好的猜测是

    • 你没有在窗口上调用ShowGraph()
    • VerticalAxisTitle 对象不是 Visual Tree 中存在的对象,与 DataGridColumn 等其他一些 WPF 对象非常相似

    要确定第一个问题是否是您的问题,只需确保您在窗口后面的构造函数中调用ShowGraph(),或者只需按照我在此处进行测试的方式设置yAxis2

    您还可以使用像 Snoop 这样的工具,它对于调试运行时数据绑定非常有用。

    如果完成后仍然无法正确显示,那么您可能需要对VerticalAxisTitle 进行更多研究,以找到如何正确绑定它的解决方法。如果您无法找到特定于 VerticalAxisTitle 的任何内容,请尝试查找 DataGridColumn 的具体情况,例如 this answer

    (附带说明一下,将公共属性大写是一个标准约定,因此您的属性应该是YAxis2。只是我的强迫症开始了。):)

    【讨论】:

    • 哈哈,谢谢你的提示。但不幸的是,这个解决方案没有运气。 Still 在调试器中被识别为正确的字符串,但不会显示。还有其他建议吗?
    • 这很奇怪,因为当值在 xaml 中硬编码时它可以工作。此外,其他绑定工作正常。
    • @RichE 查看我的答案的完整重写:)
    猜你喜欢
    • 2010-10-09
    • 1970-01-01
    • 1970-01-01
    • 2012-11-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-02-07
    • 2013-01-31
    相关资源
    最近更新 更多