1

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();
        }
    }
}
Rich E
  • 233
  • 2
  • 10

3 Answers3

0

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))

Sivasubramanian
  • 935
  • 7
  • 22
  • I was also thinking the same thing. Actually, I set `GraphWindowPresenter` as data context but I don't use anything in that class. I think I could just comment that out and it would have no effect. I bind to things strictly in the code behind of .xaml that I showed. Could something with this be causing the isuse? I did not think so since I am binding to other DP's also in the code behind in the same way, and they're working fine. Furthermore, in the debugger, I am positive that value is getting set since it shows in the debugger. – Rich E Jun 23 '14 at 18:45
  • Hi you have the set the proper datacontext. Datacontext is the object through which the controls in the xaml are going to bind to the properties. For better understanding go tthrough the link http://msdn.microsoft.com/en-us/library/ms752914(v=vs.110).aspx – Sivasubramanian Jun 23 '14 at 18:51
  • Yes, I understand that is the object through which controls the xaml. From everything I've read, though, it seems this should be working. Do you see any issues? – Rich E Jun 23 '14 at 18:52
  • Yes, the issue is you didnt provide the exact datacontext to your view. paste the datacontext setting code here – Sivasubramanian Jun 23 '14 at 18:54
  • I do not have anything setting the data context besides that `` tag. Here is the full codebehind (I added it to the original post). – Rich E Jun 23 '14 at 18:55
  • ok here what is the "thisgraphwindowinstance" ?? Binding ElementName=ThisGraphWindowInstance – Sivasubramanian Jun 23 '14 at 18:57
  • I am not sure, this was taken from a tutorial. I did try playing with it, though. It does not work without it either. – Rich E Jun 23 '14 at 18:59
  • Replace the above xaml code with this and let me know whether this helps. – Sivasubramanian Jun 23 '14 at 19:01
  • also bind using Content="{Binding yAxis2}" – Sivasubramanian Jun 23 '14 at 19:05
  • I checked and ThisGraphWindowInstance is `this` instance of `GraphWindow` and it is recognized in the debugger. I can look into the object and it is all correct. But what code did you actually want me to change? I don't see any code you pasted. – Rich E Jun 23 '14 at 19:08
  • Replace the above xaml code with the below code and let me know whether this helps. – Sivasubramanian Jun 23 '14 at 19:29
  • No, that leads to a stack overflow exception. – Rich E Jun 23 '14 at 20:22
  • Hi dude, the issue is very very simple. By debugging it, we can very easily sort out. Just attach a IValueConverter to the binding to see the bound value. The only thing is you dont know what is a datacontext and why it is used for. DependancyProperty may be new for you, since you come from Java background. but everything is DependancyProperty in WPF. Once you are aware of WPF binding mechanism. less than 2 mins you fix the issue. – Sivasubramanian Jun 24 '14 at 03:13
  • The `DataContext` doesn't matter here, since the binding in question is using `ElementName` and referring to the `` object. So it is trying to bind to `.yAxis2` – Rachel Jun 24 '14 at 15:26
  • Then attach an ivalueconverter, in the convert method put breakpoint and check what you recieve as yAxis2 inside convert method. – Sivasubramanian Jun 24 '14 at 15:39
0

Try :

      <d3:VerticalAxisTitle Content="{Binding RelativeSource={RelativeSource AncestorType=Window}, Path=yAxis2,Mode=OneWay}" />
eran otzap
  • 12,293
  • 20
  • 84
  • 139
  • Nope, it is still recognizing it in the debugger as the right string, but it wont display. Hmm.. – Rich E Jun 23 '14 at 19:10
0

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.) :)

Community
  • 1
  • 1
Rachel
  • 130,264
  • 66
  • 304
  • 490
  • Haha, thanks for the tip. But unfortunaltey, no luck with this solution. Still is recognized as the right string in the debugger, but will not display. Any other suggestions? – Rich E Jun 23 '14 at 19:14
  • It's odd because it works when the value is hardcoded in the xaml. Also, the other bindings are working fine. – Rich E Jun 23 '14 at 19:15
  • @RichE See the complete rewrite of my answer :) – Rachel Jun 24 '14 at 15:41