0

I am a newbie to WPF/XAML. I would like to get an error message if I bind to the wrong data type in XAML. It seems that XAML wants all binding to be through strings, but there are no error messages if you use an int or double by mistake.

I have found this XAML code here:

<ItemsControl ItemsSource="{Binding Path=PointList}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <Canvas />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <!--<TextBox Text="{Binding Path=Xstr, Mode=OneWay}" />-->
            <Rectangle Fill="Red" Width="25" Height="25" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
    <ItemsControl.ItemContainerStyle>
        <Style>
            <Setter Property="Canvas.Top" Value="{Binding Path=Ystr}" />
            <Setter Property="Canvas.Left" Value="{Binding Path=Xstr}" />
        </Style>
    </ItemsControl.ItemContainerStyle>
</ItemsControl>

I have used an observable collection PointList of Points(X,Y). I made the mistake at first of using integers for X and Y instead of strings. This was very difficult to debug since there was no error message when trying to bind the Canvas.Top to an integer. Is there a setting in Visual Studio to be able to catch this kind of error?


UPDATE

I have found that the binding works on an int property, but not with a public int field. Here is a Point class I created to test this out:

class Point
{
    public int _X; //I know this is usually private, this is to demonstrate
    public int _Y; //the issue with binding to a public field
    public string Xstr
    {
        get { return _X.ToString(); }
    }
    public string Ystr
    {
        get { return _Y.ToString(); }
    }
    public int X
    {
        get { return _X; }
        private set { _X = value; }
    }
    public int Y
    {
        get { return _Y; }
        private set { _Y = value; }
    }

    public Point(int x, int y)
    {
        _X = x;
        _Y = y;
    }
} 

If I bind to the int property X or string property Xstr it works fine. If I try to use the public field _X then it seems the binding cannot find the class member (even though it is public). So when a binding fails, the behavior is not the same as an exception in your code. An error like the following shows up in the output window, but the application does not stop:

System.Windows.Data Error: 40 : BindingExpression path error: '_X' property not found on 'object' ''Point' (HashCode=7877106)'. BindingExpression:Path=_X; DataItem='Point' (HashCode=7877106); target element is 'ContentPresenter' (Name=''); target property is 'Left' (type 'Double')
Community
  • 1
  • 1
joshxdr
  • 3
  • 1
  • 5
  • That's right (referring to your update). I think that nit bites me every time I switch to C# for my WPF coding. For further improvement, add implementations to the INotifyPropertyChanged interface to your Point class. – Rob Perkins Sep 19 '13 at 17:41

3 Answers3

3

seems that XAML wants all binding to be through strings

That's not true. You can bind which ever datatype you would like, as long as the property you are trying to bind to and the property you are trying to bind are from the same type, or share a certain base type.

If they are not, WPF Binding mechanism offers something called Converters which lets you convert the bounded type to the type the binded property is expecting.

By default, WPF Binding mechanism will call the ToString() method on any property you are trying to bind. in your case, calling a ToString() method on an int returns the wanted result, so no problem there.

But if you were to use a reference type for example, by default ToString() would return the type's name instead of the value you were expecting, which would cause an unexpected behaviours.

You can not catch those type of "errors". You can :

  1. See them at run-time in visual studio output window, as mentioned in the comments section.

System.Windows.Data Error: 5 : Value produced by BindingExpression is not valid for target property

  1. Pay attention to what you are binding
  2. Look for type-mismatches when seeing unexpected behaviours in bindings.

Welcome to the magic of xaml :)

Omri Btian
  • 6,499
  • 4
  • 39
  • 65
2

A data binding can use any data type. The binding system calls "ToString" or built-in converters on each item to get a representation for XAML. (You get around that by writing your own converters, which is a XAML subject all its own.)

The others are correct that .NET doesn't throw errors when there are problems with binding. This is, I've been told by the Microsoft employees who helped write it, intentional. They call it "failing gracefully".

But getting error message feedback is possible. To get better error messaging from the binding system, find the "Tools", "Options" menu item in Visual Studio. Then, go to the "Debugging" section and select the "Output Window" property category.

One of the entries there is a group called "WPF Trace Settings". Change the "Data Binding" option to "Warning" and you'll get debug-window feedback on all your failed bindings.

enter image description here

Rob Perkins
  • 3,088
  • 1
  • 30
  • 51
0

Firstly using X and Y as integer instead of string actually work.

Otherwise if you set you project as debug instead of realease, most binding error will be printed in the console output.

Benoit Catherinet
  • 3,335
  • 1
  • 13
  • 12
  • Rebuilding the example from home I was able to make X and Y work as integers. – joshxdr Sep 18 '13 at 23:55
  • To clarify, integer properties work, but integer fields do not. See the update in my original post. – joshxdr Sep 19 '13 at 15:11
  • you can see the answer of why it work on property and not field here : http://stackoverflow.com/questions/842575/why-does-wpf-support-binding-to-properties-of-an-object-but-not-fields – Benoit Catherinet Sep 19 '13 at 15:37
  • And here is a trick if the output in the debug windows is not enough for you : http://stackoverflow.com/questions/4225867/how-can-i-turn-binding-errors-into-runtime-exceptions – Benoit Catherinet Sep 19 '13 at 15:39