I have this (simplified) class which has dynamic members exposed via a IDynamicMetaObjectProvider
:
public abstract class MyDynViewModel: ViewModelBase, IDynamicMetaObjectProvider
{
public DynamicMetaObject GetMetaObject(Expression parameter)
{
return new MyDynViewModelDynamicMetaObject(parameter, this);
}
public object GetDynamicObject(string name)
{
return GetChild(name) ?? GetCommand(name);
}
}
Here is my (simplified) BindGetMember
method:
public override DynamicMetaObject BindGetMember(GetMemberBinder binder)
{
var self = Expression.Convert(Expression, LimitType);
Expression expression;
var propertyName = binder.Name;
var args = new Expression[1];
args[0] = Expression.Constant(propertyName);
expression = Expression.Call(self, typeof(MyDynViewModel).GetMethod("GetDynamicObject", BindingFlags.Public | BindingFlags.Instance), args);
var getMember = new DynamicMetaObject(expression, BindingRestrictions.GetTypeRestriction(Expression, LimitType));
return getMember;
}
Basically, GetChild(string)
and GetCommand(string)
return null
if there is no child/command that matches the name.
What happens here is that if I bind a non-existent child/command name in a XAML, the binding will successfully resolve to a null
value.
However, the behavior I would like to have is that the binding does not successfully resolve. The reason is that it would allow me to use PriorityBinding
.
So far, I got two solutions:
- throw a RuntimeBinderException if there is no matching child/command name. This is what the
dynamic
object does when you try to access an invalid member. But I think it's a bit too heavy here. - return DependencyProperty.UnsetValue, which is enough to have a
PriorityBinding
work (as explained in the documentation).
However, none of these solution lead to the usual binding error message:
System.Windows.Data Warning: 40 : BindingExpression path error: '****' property not found on 'object' ''Object' (HashCode=13794971)'. BindingExpression:Path=****; DataItem='Object' (HashCode=13794971); target element is 'TextBlock' (Name=''); target property is 'Text' (type 'String')
So, any idea/advice on the best way to achieve this behavior?