WPF databinding to interface and not actual object - casting possible?
In order to bind to explicit implemented interface members, all you need to do is to use the parentheses. For example:
implicit:
{Binding Path=MyValue}
explicit:
{Binding Path=(mynamespacealias:IMyInterface.MyValue)}
WPF databinding to interface cannot find property
There appear to have been two issues with my original post. The first is that there was a datacontext issue - thanks to James Durda for pointing this out. The row context is of type ChartDefinitionViewModel, so this code works as desired:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(selection:ChartDefinitionViewModel.HasErrors)}" Value="False">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(selection:ChartDefinitionViewModel.HasErrors)}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
Interestingly, however, binding to the HasErrors property on the IChartDefinitionViewModel interface results in a thrown exception stating that the property path is invalid, which brings me back again to my original inquiry:
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(selection:IChartDefinitionViewModel.HasErrors)}" Value="False">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(selection:IChartDefinitionViewModel.HasErrors)}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
Things, however, begin to work as expected when I bind to the interface on which the HasErrors property is directly defined.
<DataGrid.RowStyle>
<Style TargetType="{x:Type DataGridRow}">
<Style.Triggers>
<DataTrigger Binding="{Binding Path=(interfaces:IMayHaveErrors.HasErrors)}" Value="False">
<Setter Property="Background" Value="Transparent"/>
</DataTrigger>
<DataTrigger Binding="{Binding Path=(interfaces:IMayHaveErrors.HasErrors)}" Value="True">
<Setter Property="Background" Value="Red"/>
</DataTrigger>
</Style.Triggers>
</Style>
</DataGrid.RowStyle>
I'm not sure if this is an isolated case, but it appears that WPF binding can't locate properties defined upwards in the interface inheritance hierarchy, at least in this instance.
Binding WPF controls to dynamically introduced interfaces on model objects
I managed to find a solution to this problem here: WPF databinding to interface and not actual object - casting possible?
Turns out the binding will work if it is defined explicitly against the interface type, instead of implicitly, presumably because ModelObject does not have a SomeProperty, but it does have IMyInterface.SomeProperty ?
So, this works;
<DataGridTextColumn Width="Auto" Header="Some Property"
Binding="{Binding Path=(mynamespace:IMyInterface.SomeProperty), Mode=OneWay}" />
Though, it does cause designer warnings, as noted in the referenced question.
WPF: How to bind to interface that inherits from another interface?
If IEntity.Id
is an explicitly implemented property you should replace IDocument
with IEntity
in your binding path:
<TextBlock Text="{Binding Path=(documents:IEntity.Id)}"/>
If not you should be able to bind to it using the common binding syntax:
<TextBlock Text="{Binding Path=Id}"/>
Automatic template selection in WPF not working with interface
Am I doing something wrong here, or does WPF just not support this type of automatic template selection based on interfaces?
You are not doing something wrong. This kind of data binding support for interfaces is simply not supported. Please refer to Beatriz Costa's (MSFT) answer in the following thread on the MSDN forums for more information about why.
Data templates and interfaces: https://social.msdn.microsoft.com/Forums/vstudio/en-US/1e774a24-0deb-4acd-a719-32abd847041d/data-templates-and-interfaces?forum=wpf
"The data binding team discussed adding support for interfaces a while ago but ended up not implementing it because we could not come up with a good design for it. The problem was that interfaces don't have a hierarchy like object types do. Consider the scenario where your data source implements both IMyInterface1 and IMyInterface2 and you have DataTemplates for both of those interfaces in the resources: which DataTemplate do you think we should pick up?
When doing implicit data templating for object types, we first try to find a DataTemplate for the exact type, then for its parent, grandparent and so on. There is very well defined order of types for us to apply. When we talked about adding support for interfaces, we considered using reflection to find out all interfaces and adding them to the end of the list of types. The problem we encountered was defining the order of the interfaces when the type implements multiple interfaces."
So you will either have to define a DataTemplate for both Tile and TileRun explicitly or use a DataTemplateSelector.
Binding to a COM Object - Cannot resolve a Property
As far as I can remember, ComObjects
are dynamic
in .NET, so the compiler will never recognise the names of the object's properties at compile time. If that's really important for you, then just create a .NET wrapper object that implements the INotifyPropertyChanged
interface and copy all of the object's properties to your WPF object. The compiler will then obviously be able to read the names of the properties.
WPF Databinding - Getter/Setter for intermediary object not getting hit
If you want the Document to be marked dirty whenever a child's property is changed, you could subscribe to the child's PropertyChanged
event.
I'm assuming your CurrentDocument looks something like this.
public class Doc
{
public Doc()
{
_description = new CellContent();
// subscribe to changes in child
_description.PropertyChanged += DescriptionChanged;
}
private void DescriptionChanged(object sender, PropertyChangedEventArgs e)
{
Debug.Write($"I'm a dirty dirty document. Property {e.PropertyName} has changed");
}
private CellContent _description;
public CellContent Description
{
get
{
Debug.Write("I assure you this is called every time a getter of the child properties is called");
return _description;
}
// If you have a setter, don't forget to -= unsubscribe and resubscribe += after changing
}
}
WPF Databinding - PropertyChange handler not being set
You are passing the FeedStatus
property value to the OnPropertyChanged
method, instead of its name. It should look like this:
OnPropertyChanged("FeedStatus");
or better this:
OnPropertyChanged(nameof(FeedStatus));
Bind to explicit interface indexer implementation
You can not in XAML access the indexer, which is explicit implementation of interface.
What you can is to write for each interface a value converter, use appropriate converter in binding and set ConverterParameter
to the desired Key:
public class Interface1Indexer : IValueConverter
{
public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
return (value as ITestCaseInterface1)[parameter as string];
}
public object ConvertBack(object value, Type targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException("one way converter");
}
}
<TextBlock Text="{Binding Converter={StaticResource interface1Indexer}, ConverterParameter='abc'" />
And of course bound properties have to be public
, whereas explicit implementation has special state. This question can be helpful: Why Explicit Implementation of a Interface can not be public?
Related Topics
How to List All Variables of Class
C# How to Test a File Is a Jpeg
Meanings of Declaring, Instantiating, Initializing and Assigning an Object
Ref and Out Parameters in C# and Cannot Be Marked as Variant
Count the Number of Times a String Appears Within a String
How to Render a Wpf Usercontrol to a Bitmap Without Creating a Window
ASP.NET 2012 Unobtrusive Validation with Jquery
How to Generate a Cryptographically Secure Pseudorandom Number in C#
Hashset That Preserves Ordering
If Int32 Is Just an Alias for Int, How Can the Int32 Class Use an Int
Create PDF in Memory Instead of Physical File