[英]WPF Dynamic Resource Lookup Behavior with FixedPage
具有以下非常简单的xaml:
<DocumentViewer Name="dv">
<FixedDocument Name="fd" Loaded="fd_loaded">
<FixedDocument.Resources>
<Style x:Key="TestStyle">
<Style.Setters>
<Setter Property="TextBlock.Foreground" Value="BlueViolet"/>
</Style.Setters>
</Style>
<SolidColorBrush x:Key="foregroundBrush" Color="Orange"/>
</FixedDocument.Resources>
<PageContent Name="pc">
<FixedPage Name="fp" Width="800" Height="600" Name="fp">
<TextBlock Name="tb" Style="{DynamicResource TestStyle}">
Lorem ipsum
</TextBlock>
<TextBlock Foreground="{DynamicResource foregroundBrush}" Margin="20">
Lorem ipsum
</TextBlock>
</FixedPage>
</PageContent>
</FixedDocument>
</DocumentViewer>
在这里无法使用动态资源(在更复杂的情况下实际上需要使用)。 使用静态资源以所需的颜色为TextBlocks着色。 将资源移到FixedPage级别也可以解决问题。 但是我想在顶层元素上有一个通用的资源字典(因为用户可以对颜色,字体等进行运行时更改)。 将资源放在应用程序级别上也可以。 但这不是有充分理由的选择。
任何人都知道为什么这行不通。 它与TextBlock向上的逻辑树有关系吗?
MSDN资源概述指出:
查找过程在设置属性的元素定义的资源字典中检查请求的键。
然后,查找过程将逻辑树向上遍历到父元素及其资源字典。 这一直持续到到达根元素为止。
我还尝试根据以上MSDN的说明,将“画笔”和“样式”放入(虚拟)样式的资源中。 但这也不起作用。
确实有种感觉,那就不可能那么复杂,但是我很可能监督了一些事情。 任何帮助表示赞赏。
编辑
将TextBlock命名为“ tb”,然后使用tb.FindResource(“ TestStyle”)时会引发异常。 因此显然找不到该资源。 如果我签出LogicalTreeHelper.GetParent(tb)并对发现的父母重复上述操作,我将得到预期的结果:TextBlock> FixedPage> PageContent> FixedDocument ...
编辑2
这完美。 与之前计划的XAML有什么区别?
<Window x:Class="WpfDynamicStyles2.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Grid.Resources>
<SolidColorBrush x:Key="resBrush" Color="Orange"></SolidColorBrush>
</Grid.Resources>
<StackPanel>
<Button>
<TextBlock Foreground="{DynamicResource resBrush}">Dummy text...</TextBlock>
</Button>
</StackPanel>
</Grid>
</Window>
编辑3
private void fd_Loaded(object sender, RoutedEventArgs e)
{
Object obj = pc.TryFindResource("foregroundBrush");
obj = fp.TryFindResource("foregroundBrush");
obj = tb.TryFindResource("foregroundBrush");
}
无法解析放置在文本框的Foreground属性上的动态资源(实际资源位于FixedDocument.Resources级别)。 也可以在pc(PageContent),但从fp(FixedPage)和tb(TextBlock)的代码中使用TryFindResource进行工作,但它无法解析资源(obj为null)。 在XAML标记中使用静态资源时,一切正常。
顺其自然的风格是一个好的设计,但不是必需的。 要制作基于动态颜色的相同命名(键控)笔刷,我们可以将其用作动态颜色词典( 而非笔刷词典)
解决方案可以如下
DynamicResource
属性引用画笔中的颜色。 Application.Current.resources.MergedDictionaries
。 例
使用带有以下XAML的窗口制作WPF项目。
<Window.Resources> <ResourceDictionary> <ResourceDictionary.MergedDictionaries> <ResourceDictionary Source="Resources/Window11Resources.xaml"/> </ResourceDictionary.MergedDictionaries> </ResourceDictionary> </Window.Resources> <DockPanel LastChildFill="True"> <ComboBox DockPanel.Dock="Top" VerticalAlignment="Top" SelectionChanged="ComboBox_SelectionChanged" SelectedIndex="0"> <ComboBox.ItemsSource> <Collections:ArrayList> <System:String>Orange</System:String> <System:String>Red</System:String> <System:String>Blue</System:String> </Collections:ArrayList> </ComboBox.ItemsSource> </ComboBox> <DocumentViewer> <FixedDocument> <PageContent> <FixedPage Width="793.76" Height="1122.56"> <TextBlock FontSize="30" Foreground="{StaticResource LabelColorBrush}" Text="Test"/> </FixedPage> </PageContent> </FixedDocument> </DocumentViewer>
如果您观察到该窗口不需要使用任何动态的东西 。 所有引用可以保持静态。 所以LabelColorBrush
可以在字典中找到Window11Resources.xaml
在Window11Resources.xaml
词典中添加动态颜色笔刷。
<SolidColorBrush x:Key="LabelColorBrush" Color="{DynamicResource DynamicColor}"/>
在项目的某些文件夹中添加以下3种颜色笔刷字典...
<!-- Name = OrangeColorResource.xaml --> <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Color x:Key="DynamicColor">Orange</Color> </ResourceDictionary> <!-- Name = BlueColorResource.xaml --> <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Color x:Key="DynamicColor">Blue</Color> </ResourceDictionary> <!-- Name = RedColorResource.xaml --> <ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"> <Color x:Key="DynamicColor">Red</Color> </ResourceDictionary>
请注意, 键保持不变,即DynamicColor
。
现在,在App.Resources
清除并重新创建颜色字典。 我已经在Window.xaml.cs
后面的代码中完成了此Window.xaml.cs
private void ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { Application.Current.Resources.MergedDictionaries.Clear(); Application.Current.Resources.MergedDictionaries.Add( new ResourceDictionary() { Source = new Uri("Resources\\\\" + ((ComboBox)sender).SelectedItem.ToString() + "ColorResource.xaml", UriKind.RelativeOrAbsolute) }); }
现在,当您从下拉菜单中选择一种颜色时,动态颜色会在静态资源画笔上更改。 请注意,不涉及样式 。
我希望这能回答您的要求。
顺便说一句:这篇文章的原因有一些更复杂的背景。 我真的很想使用一个资源字典,从而可以在运行时(由最终用户)动态更改颜色,字体,字体大小等。 我正在研究报税表。 屏幕上显示的供用户输入的税单正在应用程序级别解析其资源。 到现在为止还挺好。
但同时我想向用户展示税收表格的打印预览,其中使用相同的资源字典(作为对象类型,而不是对象实例)来定义用于打印的配色方案,字体,字体大小等。 。 这可能与屏幕上用户输入所使用的样式不同。 这就是为什么我想在(例如)FixedDocument级别上“附加”资源字典,以便文档中的所有页面都可以引用它。 并且当更改颜色,字体等时,所有具有公共元素(TextBlocks,TextEditors等)的页面都将响应该更改。
然后我陷入了困境……正如这篇文章中所述。
现在,我有一个不错的解决方法,即创建资源字典的特定实例,将其存储为私有变量,并将其附加到我放入固定文档中的每个页面上。 它起作用了,这已经使我感到高兴。 但是我的程序员的心仍然有些痛苦,因为我更喜欢使用资源字典的单个实例,并将其放在某个顶级控件中,以便其中的所有控件都可以使用它。
作为程序员,我们也必须忍受变通方法;)如果您有任何其他建议,我愿意接受。 感谢您到目前为止的支持。
格蕾兹,乔普。
另请参阅: 有关此问题的MSDN论坛帖子
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.