- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
情况是这样的:
<DataTemplate x:Key="ItemTemplate"
DataType="local:RoutedCustomCommand">
<Button Command="{Binding}"
Content="{Binding Text}"
ToolTip="{Binding Description}">
<Button.Visibility>
<MultiBinding Converter="{StaticResource SomeConverter}">
<!-- Converter simply checks flags matching
and returns corresponding Visibility -->
<Binding Path="VisibilityModes" />
<!-- VisibilityModes is a property of local:RoutedCustomCommand -->
<Binding Path="CurrentMode"
RelativeSource="{RelativeSource AncestorType=local:CustomControl}" />
<!-- CurrentMode is a property of local:CustomControl -->
</MultiBinding>
<Button.Visibility>
</Button>
</DataTemplate>
<local:CustomControl>
<!-- ... -->
<ToolBar ...
Width="15"
ItemTemplate={StaticResource ItemTemplate}
... />
<!-- Take a look at Width - it's especially is set to such a value
which forces items placement inside adorner overflow panel -->
<!-- If you change ToolBar to ItemsControl, items won't be wrapped by adorner
panel and everything will be OK -->
<!-- ... -->
</local:CustomControl>
简而言之:当某个元素位于装饰器内部时,您不能简单地使用 Binding 的 RelativeSource 属性来访问装饰可视化树中的元素。
当我需要将它的 FontSize 绑定(bind)到工具提示的所有者 FontSize 时,我已经习惯了使用 ToolTip 遇到同样的问题 - 有非常方便的 PlacementTarget 属性,我不需要在树中查找 -绑定(bind)看起来像这样:<Binding PlacementTarget.FontSize />
这几乎是同样的问题 - 当项目在 ToolBarOverflowPanel 内部时,它似乎在装饰器内部,因此 RelativeSource 显然无法绑定(bind)。
问题是:如何解决这个棘手的问题?我真的需要绑定(bind)到容器的属性。即使我能够绑定(bind)到装饰元素,离祖先还有很长的路要走。
UPD: 最不幸的副作用是命令未到达预期目标 - 通过冒泡机制的命令传播在装饰者的可视根处停止:(。明确目标的规范遇到了同样的问题——目标必须在 local:CustomControl
内的可视化树,无法通过相同的 RelativeSource 绑定(bind)访问。
UPD2:添加可视化和逻辑树遍历结果:
UPD3: 删除了旧的遍历结果。添加更精确的遍历:
UPD4:(希望这是最终版本)。逻辑 parent 的遍历可视化树:
VisualTree
System.Windows.Controls.Button
System.Windows.Controls.ContentPresenter
System.Windows.Controls.Primitives.ToolBarOverflowPanel inherits from System.Windows.Controls.Panel
LogicalTree
System.Windows.Controls.Border
Microsoft.Windows.Themes.SystemDropShadowChrome inherits from System.Windows.Controls.Decorator
System.Windows.Controls.Primitives.Popup
System.Windows.Controls.Grid
logical root: System.Windows.Controls.Grid
System.Windows.Controls.Border
LogicalTree
Microsoft.Windows.Themes.SystemDropShadowChrome inherits from System.Windows.Controls.Decorator
System.Windows.Controls.Primitives.Popup
System.Windows.Controls.Grid
logical root: System.Windows.Controls.Grid
Microsoft.Windows.Themes.SystemDropShadowChrome inherits from System.Windows.Controls.Decorator
LogicalTree
System.Windows.Controls.Primitives.Popup
System.Windows.Controls.Grid
logical root: System.Windows.Controls.Grid
System.Windows.Documents.NonLogicalAdornerDecorator inherits from System.Windows.Documents.AdornerDecorator
LogicalTree
logical root: System.Windows.Controls.Decorator
System.Windows.Controls.Decorator
visual root: System.Windows.Controls.Primitives.PopupRoot inherits from System.Windows.FrameworkElement
LogicalTree
System.Windows.Controls.Primitives.Popup
VisualTree
System.Windows.Controls.Grid
System.Windows.Controls.Grid
here it is: System.Windows.Controls.ToolBar
System.Windows.Controls.Grid
logical root: System.Windows.Controls.Grid
提前致谢!
最佳答案
好的,现在很容易看出这里发生了什么。你原来的问题中有线索,但在你发布逻辑树之前我并不清楚你在做什么。
正如我所怀疑的,您的问题是由于缺乏逻辑继承引起的:在大多数示例中,您会在网上看到 ContentPresenter 会呈现一个 FrameworkElement,它是 ToolBar 的逻辑后代,因此事件路由和 FindAncestor 会即使在可视化树被弹出窗口打断时也能正常工作。
在您的情况下,没有逻辑树连接,因为 ContentPresenter 呈现的内容不是 FrameworkElement。
换句话说,这将允许绑定(bind)和事件路由甚至在装饰器内部工作:
<Toolbar Width="15">
<MenuItem .../>
<MenuItem .../>
</Toolbar>
但这不会:
<Toolbar Width="15">
<my:NonFrameworkElementObject />
<my:NonFrameworkElementObject />
</Toolbar>
当然,如果您的项是 FrameworkElement 派生的,它们可以是控件,您可以使用 ControlTemplate 而不是 DataTemplate。或者,它们可以是仅展示其数据项的 ContentPresenters。
如果您在代码中设置 ItemsSource,这是一个简单的更改。替换为:
MyItems.ItemsSource = ComputeItems();
用这个:
MyItems.ItemsSource = ComputeItems()
.Select(item => new ContentPresenter { Content = item });
如果您在 XAML 中设置 ItemsSource,我通常使用的技术是在我自己的类中创建附加属性(例如,“DataItemsSource”)并设置 PropertyChangedCallback,以便在设置 DataItemsSource 时,它会执行上面显示的 .Select() 创建 ContentPresenters 并设置 ItemsSource。这是肉:
public class MyItemsSourceHelper ...
{
... RegisterAttached("DataItemsSource", ..., new FrameworkPropertyMetadata
{
PropertyChangedCallback = (obj, e) =>
{
var dataSource = GetDataItemsSource(obj);
obj.SetValue(ItemsControl.ItemsSource,
dataSource==null ? null :
dataSource.Select(item => new ContentPresenter { Content = item });
}
}
这将允许它工作:
<Toolbar Width="15" DataTemplate="..."
my:MyItemsSourceHelper.DataItemsSource="{Binding myItems}" />
其中 myItems 是非 FrameworkElement
的集合那就是DataTemplate
适用于。 (使用 <Toolbar.DataItemsSource><x:Array ...
也可以内联列出项目)
另请注意,这种包装数据项的技术假定您的数据模板是通过样式而不是通过 ItemsControl.ItemTemplate property
应用的。 .如果您确实想通过 ItemsControl.ItemTemplate 应用模板,您的 ContentPresenters 需要将绑定(bind)添加到其 ContentTemplate
使用 FindAncestor 在 ItemsControl
中查找模板的属性.这是在使用“SetBinding”的“new ContentPresenter”之后完成的。
希望这对您有所帮助。
关于wpf - 绑定(bind)到装饰元素的祖先,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/1732920/
我有一个 foo 类,它有一个 bar 方法,它接受可调用的东西(函数指针/仿函数)。这个可调用的东西应该作为绑定(bind)元素传递给另一个方法 doit 和第三个方法 bar_cb 方法。 #in
我正在尝试在我的 WPF 4.0 应用程序(使用 VS 2010 Pro RTM)中创建自定义 TabItem 模板/样式,但尽管一切似乎都正常工作,但我注意到跟踪窗口中存在绑定(bind)错误。 我
作为一名刚接触 Android 的开发人员,我想我可能误解了绑定(bind)服务。 我创建了一项服务来结束对服务器的访问。作为此服务的一部分,该服务正在监听多播地址,以识别本地网络上的设备何时出现和消
这个问题在这里已经有了答案: What is the use of the JavaScript 'bind' method? (23 个回答) 关闭 7 年前。 所以我一直在尝试了解一些 JS 上
我不明白这三种语法之间的区别: where a = f (b) do a <- f (b) do let a = f (b) 我确实明白了a <- f(b)与其他两个不同,在大多数情况下,我尝试了所有
我在将 Cocoa 项目从手动同步接口(interface)模型转换为绑定(bind)模型时遇到问题,这样我就不必担心接口(interface)粘合代码。 我关注了 CocoaDevCentral C
我正在尝试找出一种好的方法来对处理大数据集的代码进行并行化,然后将结果数据导入 RavenDb。 数据处理受 CPU 限制和数据库导入 IO 限制。 我正在寻找一种解决方案,以对 Environmen
我正在 foreach 循环中生成单选按钮。我试图将选中的属性绑定(bind)到父级中的基本可观察值。不幸的是,当单击单选按钮时,父级的属性似乎没有在单击处理程序中更新。 基于一些previous w
在我的 Windows Phone 应用程序中,我有两个 LongListSelectors并排在页面上。我想做到这一点,以便当用户滚动其中一个时,另一个滚动相同的量。 两个 LongListSele
我在网上看到这个问题准备面试: Given a non-preemptive kernel which type of process will get affected morein terms o
我有一个 foreach 绑定(bind),如下所示: Summary Permitting 原因是有两个选项卡始终存在,并且我根据是否添加了其他选项卡来添加其他选项
任何人都有绑定(bind)相同的情况DataContext到 TextBlock 中的 Text 属性(例如)。 我必须分配 DataContext以我的风格反射(reflect)基于 Datacon
给定以下代码: Login 和下面的javascript $(function () { $('#btnLogin').click(function () { co
我使用 boost::asio 创建了一个服务器。我在绑定(bind)到端点时遇到问题。所以,如果我在构造函数中初始化一个接受器: Server::Server(QWidget *parent) :
我正在将现有项目从 MySQL 转换为 Postgres。代码中有相当多的原始 SQL 文字使用 ? 作为占位符,例如 SELECT id FROM users WHERE
似乎在绑定(bind)某些数据时出错了,有人可以帮我解决我哪里出错了,尽管我无法弄清楚。 真的不需要在这里显示太多,这是 Binding,我已经通过移除背景并在其中放置颜色来测试背景,效果很好。 编辑
我正在尝试使用 wcf 构建一个 http 监听器(web 服务)。这个监听器是一个更大的桌面应用程序的一部分。此桌面应用程序还会调用 http 监听器。 当监听器接收到数据时,它应该被传递到桌面应用
嘿嘿。 我正在使用 Node.JS 和 child_process 来生成 bash 进程。我试图了解我是否正在执行 I/O 绑定(bind)、CPU 绑定(bind)或两者兼而有之。 我正在使用 p
尝试执行以下操作并出现“Got interpolation ({{}}) where expression was expected”错误。 {{item.name}} 谢谢!
我有一个导入的 Java 库,它是我解决方案中的“绑定(bind)库”项目。 我正在尝试从解决方案中的另一个项目绑定(bind)到第 3 方库中的服务。 第 3 方库文档 [在 java 中] 非常简
我是一名优秀的程序员,十分优秀!