tris
tris

Reputation: 1049

Explicitly set WPF binding datatype

I wanted to ask if WPF has any functionality by which one can define a target type on a binding when the binding is done to an object of type "object". I have a generic collection of type "object" that must be handled as one object type or the other (ie. DateTime, int, etc.) at its various binding points.

Is there any way that I can arbitrarily force the .Net framework to treat objects of unknown type at compile time as objects of Type_X, on a case-by-case basis when handling bindings?

Upvotes: 3

Views: 20564

Answers (4)

esteuart
esteuart

Reputation: 1423

I'm not sure if this is exactly what you're looking for, but you can specify the type in the Path property of the binding by surrounding the property name with parenthesis and adding <Type>. in front.

Example:

<ContextMenu Tag="{Binding Path=PlacementTarget.(FrameworkElement.Tag), RelativeSource={RelativeSource Self}}">
...
</ContextMenu>

This specifies that the property Tag is a member of the FrameworkElement type and is indicating that PlacementTarget is of that type.

Upvotes: 4

akjoshi
akjoshi

Reputation: 15792

No, Binding class doesn't provide any such feature; Actually it doesn't need to, Binding framework automatically converts the source object to relevant type and uses the bound property value, or else raises a binding error if that property is not found.

So if I have a property of Object type in my ViewModel

public object Dummy 
{ 
    get 
    { 
        return dummy; 
    } 
    set 
    { 
        dummy = value;
        NotifyPropertyChanged("Dummy");
    } 
} 

and I bound it to a TextBox like this -

<TextBox Text="{Binding Dummy.Name}" HorizontalAlignment="Stretch"/>

and later set the Dummy to an object like this -

Dummy = new MyCustomType();

at this point binding will evaluate and try to find the Name property in the source object(Dummy) and if MyCustomType defines a public property named Name then binding will execute else a binding error will occur( no exception just an error msg. in output window).

Now, in case I want to set my Dummy property to objects of two different types(one having Name and other having FirstName) then I have two options -

  1. Define DataTemplates as Botz300 suggested
  2. Use a ValueConverter (which checks the object type and returns relevant property value).

Another variant of using ValueConverter is defining a TypeConverter to do conversion and declare it with the TypeConverterAttribute, then in bindings automatic conversion will be done.

Same applies for collection of objects.

Update:

Yes, WPF will implicitly use DefaultType converter to convert your type to relevant display value. In case you bind the Object directly to a property(Text in above example) then WPF will use the TypeConverter for that type(if available) or use the ToString() method to get the display value.

But all this depend on the control you are using for displaying the data and how/what you are binding.

Note: This trick only suffices for objects that can have simple textual representations. It might not make sense to use this convenient technique when dealing with complex data objects.

You can go through this article on MSDN which talks about this - Customize Data Display with Data Binding and WPF

Upvotes: 2

JCH2k
JCH2k

Reputation: 3621

Maybe you can set a designtime DataContext with d:DataContext - if you only want your IDE to know what kind of data it has to expect.

<ContextMenu ItemsSource="{Binding Shapes}"
             DataContext="{Binding Data, Source={StaticResource BindingProxy}}"
             d:DataContext="{d:DesignInstance tree:DesktopViewModel}">
    [items...]
</ContextMenu>

I have a ContextMenu which gets it's DataContext from a BindingProxy (which has a Data-Property of type object). For VS and Resharper to work correctly, they have to know the type of the DataContext, so i simply define a designtime DataContext and now they know it's a DesktopViewModel.

This only works with the DataContext, not with any binding (because there's no such thing as DesignTimeBinding), but maybe you can rewrite your bindings to refer to that DataContext (or wrap your controls in a grid which has the DataContext and d:DataContext).

Upvotes: 3

Botz3000
Botz3000

Reputation: 39640

Sure, you can use DataTemplates. If you define them in your App.xaml, they will be applied globally:

<DataTemplate DataType="{x:Type local:YourType}">
    <TextBox Text="{Binding SomeProperty}" HorizontalAlignment="Stretch"/>
</DataTemplate>

Now whenever you add an object of runtime type YourType somewhere in your UI, like in a StackPanel, that Template will be used.

Upvotes: 6

Related Questions