Alex Rivera | Logout

Strongly typed databinding in WPF/Silverlight/XAML?

Asked 2009-07-28T22:15:07.017
29

One of my biggest pet peeves with how databinding works with XAML is that there's no option to strongly type your databindings. In other words, in C#, if you want to access a property on an object that doesn't exist, you won't get any help from Intellisense, and if you insist on ignoring Intellisense, the compiler will gripe at you and won't let you proceed -- and I suspect that lots of folks here would agree that this is a Very Good Thing. But in XAML databinding, you're operating without a net. You can bind to anything, even if it doesn't exist. Indeed, given the bizarre syntax of XAML databinding, and given my own experience, it's a great deal more complicated to bind to something that does exist than to something that doesn't. I'm much more likely to get my databinding syntax wrong than to get it right; and the comparative time I spend troubleshooting XAML databindings easily dwarfs the time I spend with any other portion of Microsoft's stack (including the awkward and annoying WCF, if you can believe it). And most of that (not all of it) goes back to the fact that without strongly-typed databindings, I can't get any help from either Intellisense or the compiler.

So what I want to know is: why doesn't MS at least give us an option to have strongly-typed databindings: kind of like how in VB6, we could make any object a variant if we were really masochistic, but most of the time it made sense to use normal, typed variables. Is there any reason why MS couldn't do that?

Here's an example of what I mean. In C#, if the property "UsrID" doesn't exist, you'll get a warning from Intellisense and an error from the compiler if you try this:

string userID = myUser.UsrID;

However, in XAML, you can do this all you want:

<TextBlock Text="{Binding UsrID}" />

And neither Intellisense, the compiler, or (most astonishingly) the application itself at runtime will g

Edit
Report

1 Answer

1

Okay I could not resist, here's the Attached Property approach:

Here's the XAML:

<phone:PhoneApplicationPage.Resources>

    <!-- let's pretend this is your data source -->
    <CollectionViewSource 
        x:Key="MyViewSource" Source="{Binding}"
        converters:RestrictType.Property="Source"                  
        converters:RestrictType.Type="System.Int16" />

</phone:PhoneApplicationPage.Resources>

Here's the property code:

public class RestrictType
{
    // type
    public static String GetType(DependencyObject obj)
    {
        return (String)obj.GetValue(TypeProperty);
    }
    public static void SetType(DependencyObject obj, String value)
    {
        obj.SetValue(TypeProperty, value);
        Watch(obj);
    }
    public static readonly DependencyProperty TypeProperty =
        DependencyProperty.RegisterAttached("Type",
        typeof(String), typeof(RestrictType), null);

    // property
    public static String GetProperty(DependencyObject obj)
    {
        return (String)obj.GetValue(PropertyProperty);
    }
    public static void SetProperty(DependencyObject obj, String value)
    {
        obj.SetValue(PropertyProperty, value);
        Watch(obj);
    }
    public static readonly DependencyProperty PropertyProperty =
        DependencyProperty.RegisterAttached("Property",
        typeof(String), typeof(RestrictType), null);

    private static bool m_Watching = false;
    private static void Watch(DependencyObject element)
    {
        // element must be a FrameworkElement
        if (element == null)
            System.Diagnostics.Debugger.Break();

        // let's not start watching until each is set
        var _PropName = GetProperty(element);
        var _PropTypeName = GetType(element);
        if (_PropName == null || _PropTypeName == null)
            return;

        // we will not be setting this up twice
        if (m_Watching)
            retur
answered 2011-10-26T21:57:44.880

Your Answer