在我的WPF应用程序中,我们使用一个装饰器来显示验证消息,在特定情况下,有一个单行网格,其中有多个控件,其中一些控件具有验证功能。我遇到的问题是我想强制错误消息控件的宽度与网格相同,但似乎无法找到从adorner模板引用该网格的方法。以下是我尝试过的示例:
<ControlTemplate x:Key="Local_TopAdornedTemplateWide">
<StackPanel>
<AdornedElementPlaceholder x:Name="adornedElement"/>
<TextBlock MaxWidth="{Binding Path=ActualWidth, RelativeSource={RelativeSource FindAncestor, AncestorType=Grid}, ElementName=adornedElement}"
TextWrapping="Wrap"
Text="{Binding Converter={StaticResource Local_ValidationErrorMessageConverter}}"
Style="{DynamicResource Error_Text}"
Padding="2 1 0 0"
Visibility="{Binding ElementName=adornedElement, Mode=OneWay, Path=AdornedElement.IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"
/>
</StackPanel>
</ControlTemplate>
这会导致应用程序因XamlParseException而崩溃。
理想情况下,解决方案不会特定于网格,因此它将获得任何容器类型的宽度,但是现在网格是唯一的用例。
修改 这是我们在应用程序中使用的另一个模板的示例;这个模板对我的情况不起作用,因为它会将错误限制为上述网格的单个列的宽度:
<ControlTemplate x:Key="Local_TopAdornedErrorTemplate">
<StackPanel>
<AdornedElementPlaceholder x:Name="adornedElement"/>
<TextBlock MaxWidth="{Binding ElementName=adornedElement, Path=ActualWidth}"
TextWrapping="Wrap"
Text="{Binding Converter={StaticResource Local_ValidationErrorMessageConverter}}"
Style="{DynamicResource Error_Text}"
Padding="2 1 0 0"
Visibility="{Binding ElementName=adornedElement, Mode=OneWay, Path=AdornedElement.IsVisible, Converter={StaticResource BooleanToVisibilityConverter}}"
/>
</StackPanel>
</ControlTemplate>
使用snoop我捕获了以下两个屏幕截图(我无法使用其中一个完整堆栈以防止发布任何专有信息)
此镜头显示我之前提到的网格,其中是正在装饰的FinancialTextBox项目
此镜头显示两件事,蓝色选中的项目是上一个镜头中网格的最高祖先,黄色高亮显示是内容模板中的文本框
有了这两个,似乎很明显(基于来自Contango的回答的信息)这两个项目不在同一个视觉树中,这会让我相信我的问题是不可能的。然而,我添加的第二个模板(确实有效)表明来自装饰元素的至少一些视觉信息存在于占位符中。
所以现在我的问题归结为a)这些信息是否包括装饰元素的父元素和b)如何通过对不同元素的绑定来访问它?
答案 0 :(得分:4)
这最终比我想要的路径简单得多。
我正在阅读AdornedElementPlaceholder类并遇到this entry on MSDN,并注意到该类实际上有一个名为parent的属性,我尝试了以下绑定,它完美地运行:
MaxWidth="{Binding ElementName=adornedElement,
Mode=OneWay,
Path=AdornedElement.Parent.ActualWidth}"
答案 1 :(得分:-2)
WPF非常强大且灵活。
您可以将任何XAML标记中的任何属性绑定到任何其他XAML标记中的任何属性。
例如,您可以编写一个测试应用程序,将输入框的Text
属性绑定到标签的Text
属性,这样当您在文本框中键入内容时,标签就会出现自动更改(假设您使用UpdateSourceTrigger=PropertyChanged
)。这是XAML到XAML的直接绑定,看不到C#。
同样,您可以将错误框的宽度绑定到父控件的宽度,无论可能是什么。
Google RelativeSource
和AncestorType
,这是一个很棒的链接:
http://druss.co/2013/10/wpf-binding-examples/
看看你是否可以了解Visual Tree和Logical Tree在WPF中是如何工作的,一旦你理解了这一点,你就会更加了解绑定是如何工作的。
我还建议使用免费工具Snoop
查看可视树。 XAML Spy
非常好,但不是免费的。
Snoop
可以告诉您在运行时是否存在任何绑定错误(您设置过滤器,并列出所有错误绑定)。
您可以使用Snoop
获取源的完整XAML路径(您在上面编写的XAML),然后获取目标的完整XAML路径(即{{1} ActualWidth
然后比较它们:很快就会发现一个人不是另一个人的祖先,因为他们在视觉树的不同分支上,或者还有一些其他问题阻碍了视觉上的简单行走工作中的树。
如果您只想获得一些有用的功能,作为概念验证,请尝试使用Grid
命名目标XAML网格,并按名称而不是x:Name
引用它。