Reputation: 6651
The title is a bit blur here, I didn't find a way to say it more clearly.
Let's take a simple and very clear example of my situation:
First: I have a custom control, FooControl
, with a DependencyProperty
of type IFoo
. The control is supposed to display IFoo
objects in a DataGrid
Please note that, of course, the real object is not just about displaying some values, I could have used just a DataGrid for this matter ;)
public class FooControl : DataGrid
{
/// <summary>
/// Foo!
/// </summary>
public static readonly DependencyProperty FooProperty =
DependencyProperty.Register("Foo",
typeof(IFoo),
typeof(FooControl),
new PropertyMetadata(FooChanged));
Second: I have an IFoo
interface
public interface IFoo
{
IList<double> Values { get; set; }
}
Third: I have a Foo
object, implementing IFoo
public class Foo : IFoo
{
public IList<double> Values { get; set; }
}
And now, I want an ObservableFoo
, for binding updates purpose, here it is:
public class ObservableFoo : Foo, INotifyCollectionChanged
{
public ObservableCollection<double> ObservableValues {get; set; }
}
Now, THE PROBLEM:
I usually have my FooControl
s bound to objects of type Foo
, which are "strict" implementations of the IFoo
interface.
Now, I also need to have three FooControl
s which should be bound to objects of type ObservableFoo
(which obviously are IFoo
, but also add a property not specified in the interface, ie ObservableValues
)
in the FooControl
class, I manually set a binding to the values to be displayed:
/// <summary>
/// Sets the binding on foo values
/// </summary>
/// <param name="propertyPath">Binding path</param>
public void SetValuesBinding(string propertyPath)
{
// Binding for foovalues
Binding fooBinding = new Binding(propertyPath);
fooBinding.Converter = new FooConverter();
fooBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
fooBinding.RelativeSource = new RelativeSource(RelativeSourceMode.Self);
fooBinding.Mode = BindingMode.TwoWay;
this.SetBinding(FooControl.ItemsSourceProperty, fooBinding);
}
When propertyPath
is Foo.Values
, it works fine, updating the binding's target will call the PropertyChangedHandler
I defined for ItemsSource
When propertyPath
is Foo.ObservableValues
, updating the binding won't call the PropertyChangedHandler
I defined. However, there is no Binding error displayed on the output window!
In my comprehension of the problem, it means that:
ObservableValues
is not in IFoo
but only in ObservableFoo
, the binding tries to find IFoo.ObservableValues
and... cannot update it.How could I manage to update the binding to ObservableValues
?
I hope I made it clear enough for you guys. Please feel free to ask any question if you need me to clarify
Upvotes: 0
Views: 122
Reputation: 6651
Okay, I finally went for a workaround.
I Added a property to the FooControl
:
/// <summary>
/// The values displayed
/// </summary>
public System.Collections.IEnumerable ValuesToDisplay
{
get
{
if (this.Foo is ObservableFoo)
{
return (this.Foo as ObservableFoo).ObservableValues;
}
else if (this.Foo == null)
{
return null;
}
else
{
return this.Foo.Values;
}
}
}
And I bind the embedded Datagrid's ItemSource
to this property (using a RelativeSource
pointing to itself) and... It works fine.
But still, this made me learn something: binding does not resolve types at runtime, it will just take the specified type apparently!
Upvotes: 0
Reputation: 132618
I think the issue is with your binding.
You're binding to RelativeSource Self, which means your binding is reading FooControl.Foo.ObservableValues
, and since Foo
is defined as an IFoo
, the ObservableValues
property doesn't exist.
A possible alternative would be to set FooControl.DataContext
equal to Foo
, and then make your binding simply ObservableValues
so it is simply calling DataContext.ObservableValues
instead of FooControl.Foo.ObservableValues
If that doesn't work, try putting the ObservableValues
property on IFoo
, or make the Values
property a type which can be inherited by either IList
or ObservableCollection
such as Object
Upvotes: 1
Reputation: 19294
mmm... i don't get why you don't have ObservableFoo Implementing INotifyCollectionChanged, INotifyPropertyChanged.
Upvotes: 0