将 Binding 设置为其他 Binding 的源
我有一个 TabControl
,我想要执行以下操作:
- 获取
TabControl.Items
中的第一个和最后一个TabItem
- 获取它们的
Margin
s - 将这些
Thickness
es 提供给转换器,以将这两个结构转换为最终值
这是一个相关代码,显示我正在尝试执行的操作:
<Border.Padding>
<MultiBinding Converter="{StaticResource MarginsToPaddingConverter}">
<Binding Path="Margin">
<Binding.Source>
<Binding RelativeSource="{RelativeSource AncestorType=TabControl}" Path="Items" Converter="{StaticResource ItemCollectionToFirstItemConverter}" ConverterParameter="{x:Type TabItem}" />
</Binding.Source>
</Binding>
<Binding Path="Margin">
<Binding.Source>
<Binding RelativeSource="{RelativeSource AncestorType=TabControl}" Path="Items" Converter="{StaticResource ItemCollectionToLastItemConverter}" ConverterParameter="{x:Type TabItem}" />
</Binding.Source>
</Binding>
</MultiBinding>
</Border.Padding>
但我无法设置 Binding
作为其他 Binding
的 RelativeSource
或 Source
。基本上,手头的解决方案是创建转换器,它将采用 TabControl.Items 并将其转换为最终值,但问题是我想对两者的 Margin 进行动画处理TabItem
,所以我需要专门绑定到这些属性。如果我绑定到 TabControl.Items
,则任何 TabItem
的 Margin
都不会刷新 Border.Padding
会改变的。那我该怎么办呢?
更新
好的,所以可能的解决方案之一是挂钩 TabItem.Loaded
事件,然后使用 DependencyPropertyDescriptor
挂钩适当属性上的 Changed
事件,然后挂钩 TabItem.Items
集合中的所有项目,挂钩任何新项目并自动取消挂钩所有旧项目,并挂钩像数百万其他东西一样。但这相当复杂,大约有 400 LOC。难道就没有更简单的事情吗?最好是纯 XAML。
I have a TabControl
, and I want to do the following:
- Take first and last of the
TabItem
s inTabControl.Items
- Get their
Margin
s - Supply those
Thickness
es to the converter to convert these two structs into final value
Here is a related code showing what I am trying to do:
<Border.Padding>
<MultiBinding Converter="{StaticResource MarginsToPaddingConverter}">
<Binding Path="Margin">
<Binding.Source>
<Binding RelativeSource="{RelativeSource AncestorType=TabControl}" Path="Items" Converter="{StaticResource ItemCollectionToFirstItemConverter}" ConverterParameter="{x:Type TabItem}" />
</Binding.Source>
</Binding>
<Binding Path="Margin">
<Binding.Source>
<Binding RelativeSource="{RelativeSource AncestorType=TabControl}" Path="Items" Converter="{StaticResource ItemCollectionToLastItemConverter}" ConverterParameter="{x:Type TabItem}" />
</Binding.Source>
</Binding>
</MultiBinding>
</Border.Padding>
But I can't set Binding
as RelativeSource
or Source
of other Binding
. Basically the solution at hand is to create converter, which would take TabControl.Items
and convert it to the final value, but the problem is I want to animate Margin
s of both TabItem
s, so I need to bind specifically to these properties. If I would bind to TabControl.Items
, the Border.Padding
would not get refreshed if Margin
of any TabItem
would change. So what should I do?
Update
Ok, so one of the possible solutions is to hook into TabItem.Loaded
event, and then use DependencyPropertyDescriptor
to hook Changed
event on appropriate properties, then hook all items in TabItem.Items
collection, hook any new items and automatically unhook all old items, and hook like million other stuff. But this is quite complicated and it's like 400 LOC. Isn't there anything simpler? Preferably in pure XAML
.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
不幸的是,这个修改后的响应并不像我想要的那么优雅,但它应该有效。
基本上,使用另一个虚拟控件作为绑定的继电器。具体来说,当您想要提取集合的第一个和最后一个时,就会出现这种情况。您不能只使用转换器一次获取第一个/最后一个项目和属性,因为如果您更改第一个或最后一个项目的属性,转换器将不会接受更改。因此,您必须做一些与依赖属性相融合的事情 - 几乎就像某种二阶依赖属性会很好。
无论如何,这里有一些代码:
和一个实际的用例:
所以这里的想法是使用继电器控件抓取第一个和最后一个项目,然后绑定到那里的边距。
Unfortunately this modified response is not as elegant as I'd like, but it should work.
Basically, use another dummy control as a relay for the binding. Specifically, this scenario arises when you want to pull the first and last of a collection. You can't just use a converter to grab the first/last and the property all at once, because if you change a property on the first or last item, the converter won't pick up the change. So you have to do something that melds in with dependency properties - almost like some sort of a second order dependency property would be nice.
Anyways, here's some code:
And an actual use case:
So the idea here would be to grab the first and last item using the relay control and then bind to there margins.