- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我有一个作为 excel 插件运行的 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 对窗口的调用并将其连接到其他东西。?请注意,我无法更改上述绑定(bind),因为它不是我的控制权。
最佳答案
最直接的回答
FindAncestor 由 WPF 内部处理,并会在转到其他任何地方之前尽可能地搜索可视化树。只有当它到达一个没有视觉父项的 Visual 时,它才会在别处搜索,这取决于它到达的是什么。例如,如果它命中 FrameworkContentElement,它可以转到文档的容器。不幸的是,如果可视化树的顶部是 ElementHost,它将停止,因此无法重新路由调用。
这意味着您最简单的选择是替换绑定(bind)。幸运的是这不是很困难。
如何自动替换绑定(bind)
这是我不久前写的一个简单方法,它搜索可视化树并按照 updateFunction 的指示替换绑定(bind)。如果 updateFunction 返回的绑定(bind)与传递的绑定(bind)不同,则绑定(bind)会更新。
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);
}
}
为了说明这是如何工作的,下面是您如何编写一个方法来替换所有 RelativeSource FindAncestor 实例中的特定 AncestorType,如下所示:
static void ReplaceFindAncestorType(Visual visual, Type fromType, Type toType)
{
UpdateBindings(visual, binding =>
binding.RelativeSource.Mode != RelativeSourceMode.FindAncestor ? binding :
binding.RelativeSource.AncestorType != fromType ? binding :
new Binding
{
RelativeSource = new RelativeSource(
RelativeSourceMode.FindAncestor,
toType,
binding.RelativeSource.AncestorLevel),
Path = binding.Path,
Mode = binding.Mode,
Converter = binding.Converter,
StringFormat = binding.StringFormat,
UpdateSourceTrigger = binding.UpdateSourceTrigger,
});
}
请注意,只有常用属性会被复制到新绑定(bind)中。
ReplaceFindAncestorVisualType 方法可以像这样使用:
elementHost.LayoutUpdated += (obj, e) =>
{
ReplaceFindAncestorType(elementHost, typeof(Window), typeof(ElementHost);
};
在您的情况下,这种通用替换技术将不起作用:它将在您的 ElementHost 上寻找一个不存在的 IsActive 属性。因此,您可能需要更改的不仅仅是 RelativeSource。这意味着您的实际代码将更像这样:
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 绑定(bind)都是我们正在寻找的绑定(bind)。条件中可以根据需要添加更多条件。
替代方案
还有另一种完全不同的解决方案可用:实际上可以在无边框窗口中承载内容并添加自定义代码以保持此窗口位于 ElementHost 之上,因此它看起来位于另一个窗口内。这比听起来更棘手,因为您必须处理诸如 ActiveWindow、ForegroundWindow、Z 顺序、最小化状态、键盘焦点等内容。但如果您的需求非常简单,这可能是一个合理的解决方案。
关于wpf - 拦截 RelativeSource FindAncestor,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/2402280/
这是代码: item1
我有一个作为 excel 插件运行的 WPF 应用程序,它有这样的可视化树 精益求精 元素主机 WPF 用户控件 WPF 色带条控件 现在,在 excel 中加载插件时,不会启用位于 WPF 功能区栏
是 FindAncestor在Window的整个Visual树中搜索一个元素? 如果是,那我该如何改进呢? 是 binding data error如果我们通过使用 Find Ancestor 找到一
FindAncestor 的一件特别的事情让我很困惑,看看下面的例子:
我是 WPF 和 MVVM 模式的新手,所以我的绑定(bind)有一些问题。 在客户的详细信息 View 中,我想在组合框中列出一些状态。 在我的 ViewModel 中,客户处于根级别,状态列表也是
对于以下 MultiBinding 表达式,如果多次更改 PropB,绑定(bind)引擎将搜索 DataGrid 祖先多少次? 如果 PropertyC(及其路径)
本文整理了Java中org.carewebframework.ui.zk.ZKUtil.findAncestor()方法的一些代码示例,展示了ZKUtil.findAncestor()的具体用法。这些
我有一个绑定(bind)到对象的 ItemsControl,在 ItemsControl 的数据模板中,我有两个文本 block ,我想将第一个文本 block 的文本属性绑定(bind)到位于此 I
很难说出这里问的是什么。这个问题是模棱两可的、模糊的、不完整的、过于宽泛的或修辞的,无法以目前的形式得到合理的回答。如需帮助澄清这个问题以便重新打开它,visit the help center .
我正在创建一个 MVVM 应用程序,它有两个 View 模型,RegisterUserViewModel 和 UserViewModel。 “RegisterUserViewModel”有一个公共(p
这个问题在这里已经有了答案: How to hide wpf datagrid columns depending on a property (5 个回答) 9年前关闭。 我收到此错误: Canno
我目前正在 WPF 用户控件中工作(我的 XAML 文件的根元素是“UserControl”),我知道该控件托管在 Window 内。如何使用数据绑定(bind)访问窗口的属性? 有谁知道为什么 不
我有一个订单列表,当订单状态为已取消时,我想使文本闪烁。到目前为止,我的代码有效。然而,有时它会抛出异常: WinRT information: Cannot resolve TargetName l
我的问题是关于将一个元素的属性正确绑定(bind)到另一个元素。 这是我的代码的结构: 数据模板包含一个网格(我们称之为网格 GridA),在网格中,我指定了一个控件的实例,称为 ControlA
我正在尝试使用 WPFToolkit 的 DataGrid 控件(和 C#/.Net 3.5)来显示每条记录的 ComboBox。使用下面的代码,组合框会显示出来,但它们的下拉菜单不包含任何项目:
我正在制作一个列表框的模板。我喜欢仅在项目被选中时显示路径。 数据模板: ...
我正在制作一个列表框的模板。我喜欢仅在项目被选中时显示路径。 数据模板: ...
我从下面的代码中得到以下错误...不知道为什么(是的,它产生所有 4 个,即使它是相同的 2 个重复)。哦,它不会产生交替行效果,即使在弹出这些错误之前相同的代码正在运行。 System.Window
有人知道 XAML 绑定(bind)中 FindAncestor 的“新方式”是什么吗?查看RelativeSourceMode ( http://msdn.microsoft.com/en-us/l
我写了样式: 仅当对包含此 ListBoxItem 的 ListBox 应用分组时才相关。但是,大多数时候它不在分组中,这会导致数十、数百和数千个绑定(bind)异常(取
我是一名优秀的程序员,十分优秀!