我得到了一个工作的自定义标记扩展,它以一种特定的方式从DataContext中检索信息(对于这个问题来说并不重要)。
在不属于可视或逻辑树的元素中使用此标记扩展之前,一切都很顺利。在元素InputBindings中的特定示例中。在这个场景中,我得到了一个FrameworkElement (KeyBinding),而不是以DependencyObject的形式检索一个Freezable。
如何通过代码访问 DataContext ?
我的XAML代码:
<UserControl.InputBindings>
<KeyBinding
Key="CapsLock"
Command="{wtc:CommandBinding {x:Static b:Commands.OpenTimeLine}}" />
</UserControl.InputBindings>我通常检索DataContext的自定义标记扩展中的代码
protected override object ProvideValue(
DependencyObject dependencyObject,
DependencyProperty dependencyProperty )
{
if ( dependencyObject is Freezable )
{
// TODO: How to handle freezable?
}
_frameworkElement = dependencyObject as FrameworkElement;
if ( _frameworkElement == null )
{
throw new InvalidImplementationException(
"The DataContextBinding may only be used on framework elements." );
}
if ( !_dataContextChangedHooked )
{
_frameworkElement.DataContextChanged += DataContextChanged;
_dataContextChangedHooked = true;
}
return ProvideValue( _frameworkElement.DataContext );
}整个源代码也是在线的。我有相当广泛的标记扩展类层次结构。
AbstractMarkupExtension⇐AbstractDependencyPropertyBindingExtension⇐AbstractDataContextBindingExtension CommandBindingExtension
发布于 2012-01-30 13:39:22
一种解决办法令人惊讶地容易。假设您要查找的DataContext与根对象的DataContext相同,您可以简单地使用IRootObjectProvider。此提供程序可通过IServiceProvider访问,后者作为ProvideValue的参数传递。
var rootProvider = (IRootObjectProvider)ServiceProvider
.GetService( typeof( IRootObjectProvider ) );
_frameworkElement = rootProvider.RootObject as FrameworkElement;可能有更复杂的场景,您必须遍历树(通过LogicalChildren)才能找到所需的DataContext。
发布于 2012-01-27 16:51:18
这是一种令人讨厌的反思方式:
var context = (FrameworkElement)typeof(DependencyObject)
.GetProperty("InheritanceContext", BindingFlags.NonPublic | BindingFlags.Instance)
.GetValue(dependencyObject, null);
var datacontext = context.DataContext;(对FrameworkElement的强制转换是不安全的,InheritanceContext也是DependencyObject类型的,InheritanceContext通常是声明使用Freezable的属性的对象,如果它不是需要递归的FrameworkElement )
https://stackoverflow.com/questions/9036738
复制相似问题