Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/wpf/13.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Wpf 截获相对资源查找器_Wpf_Wpf Controls_Binding_Ribbon Control - Fatal编程技术网

Wpf 截获相对资源查找器

Wpf 截获相对资源查找器,wpf,wpf-controls,binding,ribbon-control,Wpf,Wpf Controls,Binding,Ribbon Control,我有一个作为excel插件运行的WPF应用程序,它的可视化树如下 胜过 元素主机 WPF用户控制 WPF功能区条控件 现在,当插件加载到excel中时,WPF功能区栏控件上的任何控件都不会启用。请参阅下面的错误 System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows

我有一个作为excel插件运行的WPF应用程序,它的可视化树如下

  • 胜过
    • 元素主机
      • WPF用户控制
        • WPF功能区条控件
现在,当插件加载到excel中时,WPF功能区栏控件上的任何控件都不会启用。请参阅下面的错误

System.Windows.Data Error: 4 : Cannot find source for binding with 
reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Window', AncestorLevel='1''. BindingExpression:Path=IsActive; DataItem=null; target element 
is 'Ribbon' (Name=''); target property is 'NoTarget' (type 'Object')
如果将功能区栏控件嵌套在独立窗口(excel外部)中,则效果良好


有没有办法截获FindAncestor调用窗口并将其连接到其他对象。?请注意,我无法更改上述绑定,因为它不是我的控件。

在Excel中使用该控件时,祖先中没有窗口,但是,您可以使用查找绑定的定义位置,然后在运行时查找依赖项对象(按类型)并更改其属性的绑定表达式?

另一个选项是添加一个作为祖先从Windows继承的自定义控件,然后将其绑定到Excel控件。

最直接的答案是

FindAncestor由WPF在内部处理,并将在前往其他任何地方之前尽可能地搜索可视化树。只有当它到达一个没有视觉父对象的视觉对象时,它才会在别处搜索,这取决于它到达的对象。例如,如果它命中FrameworkContentElement,则可以转到文档的容器。不幸的是,如果可视化树的顶部是ElementHost,它将停止,因此无法重新路由调用

这意味着您最简单的选择是替换绑定。幸运的是,这并不十分困难

如何自动替换绑定

这是我不久前写的一个简单方法,它搜索可视化树并按照updateFunction的指示替换绑定。如果updateFunction返回的绑定与传递的绑定不同,则会更新该绑定

static void UpdateBindings(Visual visual, Func<Binding, Binding> updateFunction)
{
  if(visual==null) return;
  for(int i=0; i<VisualTreeHelper.GetChildrenCount(visual); i++)
    UpdateBindings(VisualTreeHelper.GetChild(visual, i) as Visual, updateFunction);
  for(var enumerator = visual.GetLocalValueEnumerator(); enumerator.MoveNext(); )
  {
    var property = enumerator.Current.Property;
    var binding = BindingOperations.GetBinding(visual, property);
    if(binding==null) continue;
    var newBinding = updateFunction(binding);
    if(newBinding!=binding)
      BindingOperations.SetBinding(visual, property, newBinding);
  }
}
请注意,只有常用的属性才会复制到新绑定

ReplaceFindAncestorVisualType方法可以使用如下方式:

elementHost.LayoutUpdated += (obj, e) =>
{
  ReplaceFindAncestorType(elementHost, typeof(Window), typeof(ElementHost);
};
elementHost.LayoutUpdated += (obj, e) =>
{
  UpdateBindings(elementHost, binding =>
    binding.RelativeSource.AncestorType != typeof(Window) ? binding :
    new Binding
    {
      Source = ultimateContainingWindowOrOtherObjectHavingIsActiveProperty,
      Path = new PropertyPath("IsActive"), // Put property name here
    });
};
在您的情况下,这种通用替换技术将不起作用:它将在ElementHost上查找不存在的IsActive属性。所以你可能需要改变的不仅仅是相对资源。这意味着您的实际代码将更像这样:

elementHost.LayoutUpdated += (obj, e) =>
{
  ReplaceFindAncestorType(elementHost, typeof(Window), typeof(ElementHost);
};
elementHost.LayoutUpdated += (obj, e) =>
{
  UpdateBindings(elementHost, binding =>
    binding.RelativeSource.AncestorType != typeof(Window) ? binding :
    new Binding
    {
      Source = ultimateContainingWindowOrOtherObjectHavingIsActiveProperty,
      Path = new PropertyPath("IsActive"), // Put property name here
    });
};
注意,上面的代码假设任何FindAncestor:Window绑定都是我们正在寻找的绑定。可以根据需要在条件列表中添加更多条件

替代解决方案


还有另一个完全不同的解决方案:可以在无边界窗口中实际承载内容,并添加自定义代码以将此窗口定位在ElementHost上,使其看起来位于另一个窗口中。这比听起来更复杂,因为你必须处理诸如ActiveWindow、ForegroundWindow、Z顺序、最小化状态、键盘焦点、,等等。但如果您的需求非常简单,这可能是一个合理的解决方案。

您不能在运行时通过遍历树并使用“BindingOperations.GetBinding”获取绑定,然后更改绑定的RelativeSource属性来获取Ribbon控件吗?您好,我应该为哪个属性检索绑定。。我不知道控件的哪个属性正在尝试绑定。“目标属性是‘NotTarget’。GetBinding需要指定dependencyproperty。这不起作用,因为所有控件都以ElementHost为父控件,并且无法将窗口添加到ElementHost。我已经从上面给出的错误消息中找到了有问题的控件。该控件是Ribbon。但我不知道是哪个控件。”控件的依赖项属性具有此失败的绑定表达式。请使用Snoop,并在输出窗口中重新读取绑定错误消息-您应该在该窗口中找到依赖项属性名称。如错误消息中所述,依赖项属性名称不可用。此外,在excel中承载时,Snoop无法窥探托管内容.