I am writing a composite loosely coupled MVVM WPF application and child VMs in a parent VM are interfaces rather than class instances, e.g.
public IChildViewModel { get; set; }
Now how do I render this property using a DataTemplate? like:
<DataTemplate DataType="{x:Type contracts:IChildViewModel}">
I understand due to the nature of interfaces (multiple inheritance etc.) WPF does not allow this direct binding. But as interfaces should be used widely in loosely coupled applications, is there any workaround to bind DataTemplate to interfaces? Thanks.
A data template can contain elements that are each bound to a data property along with additional markup that describes layout, color and other appearance. DataTemplate is, basically, used to specify the appearance of data displayed by a control not the appearance of the control itself.
A ControlTemplate will generally only contain TemplateBinding expressions, binding back to the properties on the control itself, while a DataTemplate will contain standard Binding expressions, binding to the properties of its DataContext (the business/domain object or view model).
WPF provides various templates for customization of controls. WPF ListView ItemTemplate is in one of these. ItemTemplate of ListView is useful when we have to change the visual presentation of bound data objects.
You can bind to interfaces by telling wpf explicitly that you are binding to an interface field:
(Please note that ViewModelBase is simply a base-class that implements the INotifyPropertyChanged interface)
public class Implementation : ViewModelBase, IInterface { private string textField; public string TextField { get { return textField; } set { if (value == textField) return; textField = value; OnPropertyChanged(); } } } public interface IInterface { string TextField { get; set; } }
Then on the ViewModel:
private IInterface interfaceContent; public IInterface InterfaceContent { get { return interfaceContent; } }
And finally the Xaml that makes it possible:
<ContentControl Grid.Row="1" Grid.Column="0" Content="{Binding InterfaceContent}"> <ContentControl.ContentTemplate> <DataTemplate DataType="{x:Type viewModels:IInterface}"> <TextBox Text="{Binding Path=(viewModels:IInterface.TextField)}"/> </DataTemplate> </ContentControl.ContentTemplate> </ContentControl>
As you can see, the binding refers explicitly to the 'IInterface' definiton.
It seems that using a DataTemplateSelector
is the way to go in such situations.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With