Вот ошибка, которую вы увидите, если посмотрите на панель «Вывод» в VS во время выполнения:
Не удается найти управляющий FrameworkElement или FrameworkContentElement для целевого элемента. BindingExpression: Path = Id;DataItem = NULL;целевым элементом является SomeDependencyProp (HashCode = 11898202);Свойство target - SubProp (тип Int32)
Добавьте трассировку к привязке ({Binding Id, PresentationTraceSources.TraceLevel=High}
), и вы увидите много болтовни о "Framework ментора не найден". Проблема здесь в том, что правило проверки находится за пределами визуального дерева, поэтому DataContext не наследуется ни от одного из родителей (следовательно, DataItem = null в сообщении об ошибке выше). {Binding Id}
терпит неудачу, потому что нет источника;он не знает, где искать свойство Id
.
Каноническим решением этой ситуации является использование BindingProxy. Каноническим способом написания связующего прокси-класса является поиск в Google слова «stackoverflow bindingproxy wpf» или чего-то в этом роде и кража первого найденного вами .
public class BindingProxy : Freezable
{
#region Overrides of Freezable
protected override Freezable CreateInstanceCore()
{
return new BindingProxy();
}
#endregion
public object Data
{
get { return (object)GetValue(DataProperty); }
set { SetValue(DataProperty, value); }
}
// Using a DependencyProperty as the backing store for Data.
// This enables animation, styling, binding, etc...
public static readonly DependencyProperty DataProperty =
DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy),
new UIPropertyMetadata(null));
}
Затем используйте так:
<TextBox>
<TextBox.Resources>
<local:BindingProxy x:Key="DataContextProxy" Data="{Binding}" />
</TextBox.Resources>
<TextBox.Text>
<Binding Path="Name" ValidatesOnDataErrors="True">
<Binding.ValidationRules>
<xns:MyValidationRule>
<xns:MyValidationRule.SomeDependencyProp>
<xns:SomeDependencyProp
SubProp="{Binding Data.Id, Source={StaticResource DataContextProxy}}"
/>
</xns:MyValidationRule.SomeDependencyProp>
</xns:MyValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
Если вы создадите BindingProxy в DataTemplate.Resources вместо TextBox.Resources, вы снова получите «наставник фреймворка не найден». Выше работает для меня.