使用Findresource加载资源会引发异常 - WPF / C#

时间:2022-05-01 14:14:27

I am writing a CustomControl in WPF. I have some DataTemplates in my Themes/Generic.xaml, at the resourcedictionary level, with x:Key assigned for them.

我在WPF中编写CustomControl。我在我的Themes / Generic.xaml中有一些DataTemplates,在resourcedictionary级别,为它们分配了x:Key。

Now from within the same control class code, i want to find and load that resource so i can dynamically assing to something in the code.

现在从同一个控件类代码中,我想找到并加载该资源,这样我就可以动态地为代码中的某些东西做出贡献。

I have tried base/this.FindResource("keyvalue"), this.Resources[""] etc.

我试过base / this.FindResource(“keyvalue”),this.Resources [“”]等。

It keeps returning that the resource is not found and hence null.

它一直返回找不到资源,因此为null。

The resource is defenitely there in the generic.xaml.

该资源在generic.xaml中非常有用。

Please help.

7 个解决方案

#1


6  

A bit late for an answer, but it might benefit the others.

回答有点迟,但可能会让其他人受益。

The resource you're trying to access is at the theme level, to access it from anywhere in your assembly it must be identified by ComponentResourceKey:

您尝试访问的资源位于主题级别,要从程序集中的任何位置访问它,必须由ComponentResourceKey标识:

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

then in your XAML you'd reference it like this:

然后在你的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>

and in your code like this:

在你的代码中像这样:

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

There is also a verbose form of XAML syntax that looks like this (but its just the same thing):

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

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

Note that even though the TypeInTargetAssembly must be set it does not restrict access to this resource for other types in assembly.

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

#2


3  

Make sure that you have actually added the custom control as a child to another control before using the FindResource on it. I'm pretty sure that when you use FindResource, it climbs the control hierarchy until it finds a match. If your control has no parent, it will not find the resource you are looking for.

在使用FindResource之前,请确保您已将自定义控件作为子项添加到另一个控件。我很确定当你使用FindResource时,它会爬上控件层次结构,直到找到匹配为止。如果您的控件没有父级,则无法找到您要查找的资源。

#3


2  

You can load the resource dictionary like this:

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

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

You can then find resources within it in the usual manner, e.g., myDictionary["keyvalue"]

然后,您可以通常的方式查找其中的资源,例如myDictionary [“keyvalue”]

#4


1  

Since you're building a custom control I presume that you have a ControlTemplate defined in your generic.xaml file? If so, then if you add your DataTemplate(s) to the Resources section of the ControlTemplate like this:

由于您正在构建自定义控件,我假设您在generic.xaml文件中定义了ControlTemplate?如果是这样,那么如果你将DataTemplate添加到ControlTemplate的Resources部分,如下所示:

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

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

then provided that the control template has been applied/loaded then you'll be able to find that data templates using a call to this.FindResource() within your control.

然后,如果已经应用/加载了控件模板,那么您将能够在控件中使用对this.FindResource()的调用来查找数据模板。

#5


1  

x:Key and DataType are mutualy exclusiv. Internally, if you set DataType, WPF generates a key of type DataTemplateKey. So a call of FindResource with ComponentResourceKey throws an exception, because the resource can't be found with this key. Use

x:Key和DataType是mutualy exclusiv。在内部,如果设置DataType,WPF会生成一个DataTemplateKey类型的键。因此,使用ComponentResourceKey调用FindResource会引发异常,因为使用此密钥无法找到该资源。使用

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

for a DataTemplate with DataType={x:Type local:yourType} defined or

对于DataTemplate,其中DataType = {x:Type local:yourType}已定义或

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

for a DataTemplate with x:Key={ComponentResourceKey TypeInAssembly={x:Type l:yourType}, ResourceId=ressId} defined. Don't define DataType and x:Key in the same template.

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

#6


0  

Im not sure i think you need to define in the of the XAML your using or the a static resource with a new x:Key that corrisponds to what you want to change.

我不确定我是否认为您需要在XAML中定义您的使用或静态资源以及新的x:Key,它与您想要更改的内容相对应。

another option is if you use a file that contains the template merge the resources like this:

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

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

in the appropriate place your going to try and find the resource

在适当的地方你去尝试找到资源

HTH, Eric

#7


0  

Thnaks to both.

对两者都有吸引力。

I tried moving the resources into CT's resources section. Even then when i look up at runtime, say in OnApplyTemplate or EndInit() etc., the this.Resources has no objects in it :-( although its all ther ein the control's Generic.xaml.

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

So it returns null at all times.

所以它始终返回null。

#1


6  

A bit late for an answer, but it might benefit the others.

回答有点迟,但可能会让其他人受益。

The resource you're trying to access is at the theme level, to access it from anywhere in your assembly it must be identified by ComponentResourceKey:

您尝试访问的资源位于主题级别,要从程序集中的任何位置访问它,必须由ComponentResourceKey标识:

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

then in your XAML you'd reference it like this:

然后在你的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>

and in your code like this:

在你的代码中像这样:

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

There is also a verbose form of XAML syntax that looks like this (but its just the same thing):

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

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

Note that even though the TypeInTargetAssembly must be set it does not restrict access to this resource for other types in assembly.

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

#2


3  

Make sure that you have actually added the custom control as a child to another control before using the FindResource on it. I'm pretty sure that when you use FindResource, it climbs the control hierarchy until it finds a match. If your control has no parent, it will not find the resource you are looking for.

在使用FindResource之前,请确保您已将自定义控件作为子项添加到另一个控件。我很确定当你使用FindResource时,它会爬上控件层次结构,直到找到匹配为止。如果您的控件没有父级,则无法找到您要查找的资源。

#3


2  

You can load the resource dictionary like this:

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

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

You can then find resources within it in the usual manner, e.g., myDictionary["keyvalue"]

然后,您可以通常的方式查找其中的资源,例如myDictionary [“keyvalue”]

#4


1  

Since you're building a custom control I presume that you have a ControlTemplate defined in your generic.xaml file? If so, then if you add your DataTemplate(s) to the Resources section of the ControlTemplate like this:

由于您正在构建自定义控件,我假设您在generic.xaml文件中定义了ControlTemplate?如果是这样,那么如果你将DataTemplate添加到ControlTemplate的Resources部分,如下所示:

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

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

then provided that the control template has been applied/loaded then you'll be able to find that data templates using a call to this.FindResource() within your control.

然后,如果已经应用/加载了控件模板,那么您将能够在控件中使用对this.FindResource()的调用来查找数据模板。

#5


1  

x:Key and DataType are mutualy exclusiv. Internally, if you set DataType, WPF generates a key of type DataTemplateKey. So a call of FindResource with ComponentResourceKey throws an exception, because the resource can't be found with this key. Use

x:Key和DataType是mutualy exclusiv。在内部,如果设置DataType,WPF会生成一个DataTemplateKey类型的键。因此,使用ComponentResourceKey调用FindResource会引发异常,因为使用此密钥无法找到该资源。使用

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

for a DataTemplate with DataType={x:Type local:yourType} defined or

对于DataTemplate,其中DataType = {x:Type local:yourType}已定义或

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

for a DataTemplate with x:Key={ComponentResourceKey TypeInAssembly={x:Type l:yourType}, ResourceId=ressId} defined. Don't define DataType and x:Key in the same template.

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

#6


0  

Im not sure i think you need to define in the of the XAML your using or the a static resource with a new x:Key that corrisponds to what you want to change.

我不确定我是否认为您需要在XAML中定义您的使用或静态资源以及新的x:Key,它与您想要更改的内容相对应。

another option is if you use a file that contains the template merge the resources like this:

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

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

in the appropriate place your going to try and find the resource

在适当的地方你去尝试找到资源

HTH, Eric

#7


0  

Thnaks to both.

对两者都有吸引力。

I tried moving the resources into CT's resources section. Even then when i look up at runtime, say in OnApplyTemplate or EndInit() etc., the this.Resources has no objects in it :-( although its all ther ein the control's Generic.xaml.

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

So it returns null at all times.

所以它始终返回null。