使用Findresource加载资源时抛出异常 - WPF/C#

4
我正在编写一个WPF自定义控件。我在我的Themes/Generic.xaml中有一些DataTemplates,它们在资源字典级别上有x:Key分配。
现在我想从同一控件类代码中查找和加载该资源,以便我可以在代码中动态地分配给某些东西。
我尝试过base/this.FindResource("keyvalue")、this.Resources[""]等方法。
它不断返回未找到资源,因此为null。
该资源绝对存在于generic.xaml中。
请帮忙。
7个回答

7

虽然有点晚了,但这个答案可能对其他人有好处。

你尝试访问的资源是主题级别的,如果想从程序集的任何地方访问它,必须使用ComponentResourceKey进行标识:

<Style TargetType="{x:Type TreeViewItem}" 
       x:Key="{ComponentResourceKey {x:Type local:MyTVIStyleSelector}, tviBaseStyle}">
  <!-- style setters -->
</Style>

然后在您的XAML中,您将像这样引用它:

<Style TargetType="{x:Type TreeViewItem}" 
       x:Key="{ComponentResourceKey {x:Type local:MyTVIStyleSelector}, tviStyle_1}"
       BasedOn={StaticResource {ComponentResourceKey {x:Type local:MyTVIStyleSelector}, tviBaseStyle}}>
  <!-- style setters -->
</Style>

并且在你的代码中像这样:

ComponentResourceKey key = new ComponentResourceKey(typeof(MyTVIStyleSelector), "tviStyle_1");
Style style = (Style)Application.Current.TryFindResource(key);

还有一种冗长的XAML语法形式,看起来像这样(但其实是一样的):

<Style TargetType="{x:Type TreeViewItem}" 
       x:Key="{ComponentResourceKey TypeInTargetAssembly={x:Type local:MyTVIStyleSelector}, ResourceId=tviBaseStyle}">
  <!-- style setters -->
</Style>

请注意,即使设置了TypeInTargetAssembly,它也不会限制其他类型在程序集中访问此资源。

这种技术能帮我解决这个问题吗?https://dev59.com/jG3Xa4cB1Zd3GeqPha1B#14528823 我正在尝试在Generic.xaml中找到资源的实例。 - Dr. Andrew Burnett-Thompson

3

在使用FindResource之前,请确保您已将自定义控件添加为其他控件的子控件。我相信,当您使用FindResource时,它会上溯控件层次结构,直到找到匹配项。如果您的控件没有父控件,它将无法找到您要查找的资源。


2
您可以这样加载资源字典:

ResourceDictionary myDictionary = Application.LoadComponent(new Uri("/MyAssembly;component/Themes/Generic.xaml", UriKind.RelativeOrAbsolute)) as ResourceDictionary;

您可以按照通常的方式在其中查找资源,例如:myDictionary["keyvalue"]。


1

x:Key和DataType是互斥的。如果设置了DataType,WPF会生成一个DataTemplateKey类型的键。因此,使用ComponentResourceKey调用FindResource会抛出异常,因为无法使用此键找到资源。请使用

frameworkElement.FindResource(new DataTemplateKey(typeof(yourType)));

对于定义了 DataType={x:Type local:yourType} 的 DataTemplate 或

frameworkElement.FindResource(new ComponentResourceKey(typeof(yourType), "ressId"));

对于一个具有x:Key={ComponentResourceKey TypeInAssembly={x:Type l:yourType}, ResourceId=ressId}定义的DataTemplate。不要在同一模板中定义DataType和x:Key。


1

由于您正在构建自定义控件,我假设您在generic.xaml文件中定义了一个ControlTemplate? 如果是这样的话,如果您像这样将DataTemplate添加到ControlTemplate的资源部分:

<ControlTemplate>
    <ControlTemplate.Resources>
        <!-- Data Templates Here -->
    </ControlTemplate.Resources>

    <!-- Rest of Control Template -->
</ControlTemplate>

只要控件模板已应用/加载,您就可以在控件中使用 this.FindResource() 调用来查找数据模板。


0

感谢两位。

我尝试将资源移动到 CT 的资源部分。即使这样,在运行时查看,比如在 OnApplyTemplate 或 EndInit() 中等等,this.Resources 中没有任何对象 :-( 尽管它们都在控件的 Generic.xaml 中。

因此它始终返回 null。


0

我不确定,但我认为你需要在使用的XAML文件中定义或者在<Window.Resources>标签内定义一个新的静态资源,并且给它一个对应你想要更改的内容的x:Key。

另一种选择是,如果你使用了包含模板的文件,可以像这样合并资源:

<ResourceDictionary.MergedDictionaries>
  <ResourceDictionary Source="SomeTemplate.xaml"/>
</ResourceDictionary.MergedDictionaries>

在适当的位置,你将尝试找到资源。

希望有所帮助, Eric


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接