简体   繁体   中英

WPF Binding with Dependency Properties. Issue with Data Not Displaying

I have tried all morning to get this to work with no luck. I am using DynamicDataDisplay (D3) to display a graph. Here is my simple view defined using 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>

The issue is that the:

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

in the InjectedPlotter does not display at all when I use the current setup with the Content bound to Path=yAxis2 . I set at breakpoint and I see that yAxis2 is actually a defined string and that it is not null.

When I actually hardcode a value such that Content="DEFAULT TITLE" , so it then becomes :

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

the title displays fine.

Does anyone know why this is happening?

Here is the code behind for reference:

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!";
     .....
}

EDIT >>>>>>>>>

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();
        }
    }
}

In the code you provided, you have set the datacontext as an object of GraphWindowPresenter, but while declaring the dependancy property you have set the GraphWindowView object. Please make sure that you set the appropriate object as datacontext

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

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

尝试:

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

I ran a quick test binding a TextBox.Text , and the code you have posted works.

<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";
    }

}

So my best guess is that either

  • you are not calling ShowGraph() on the window
  • or the VerticalAxisTitle object is not one that exists in the Visual Tree, much like some other WPF objects like DataGridColumn

To determine if the first issue is your problem, simply ensure you are calling ShowGraph() in the constructor behind your window, or just set yAxis2 the way I have here for testing.

You could also use a tool like Snoop that is very useful for debugging runtime databindings.

If that is done and it's still not showing up correctly, then you may need to do some more research into the VerticalAxisTitle to find workarounds on how to bind it correctly. If you have trouble finding anything specific to VerticalAxisTitle , try looking up how it's done for DataGridColumn , such as this answer .

(As a side note, it's a standard convention to capitalize public properties, so your property should be YAxis2 . Just my OCD kicking in.) :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM