Reputation: 1049
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
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
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 -
DataTemplates
as Botz300 suggested 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
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
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