Wpf Databinding to Interface and Not Actual Object - Casting Possible

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



Leave a reply



Submit