I've defined a style resouce in MainWindow.xaml as follows:
<Window.Resources>
<Style x:Key="PageHeader" TargetType="TextBlock">
...
I'm then trying to use it for a TextBlock element in a user control:
<TextBlock Style="{StaticResource PageHeader}">Welcome!</TextBlock>
However, I get the error:
The resource "PageHeader" could not be resolved.
There are no syntax errors in the style specification that I can see. The resolve error is all I get.
I've also tried setting the TargetType to an x:Type too to no avail. Any pointers here?
This is in two different files, right? It's out of scope. All user controls inherit from their visual parent is inherited dependency properties, like text formatting. DataContext is inherited, but appears not to be inherited by the same mechanism. Resources are not inherited.
Try putting the Style in App.xaml, or in a resource dictionary XAML file that's explicitly included in App.xaml. Everybody gets what's in App.xaml.
Related
I have a grid that I am trying to hook up a visibility converter to. I have a class set up in the HelperObjects namespace, but for some reason the xaml is not picking up the reference. The error message is "The resource BoolToVisConverter could not be resolved" Why won't the xaml pull in this resource? I am sure I am doing something ridiculous here...
Here is the xaml:
xmlns:HelperObjects="clr-namespace:foo.HelperObjects"
...
<Grid Visibility="{Binding isZoneTwoVisible, Converter={StaticResource BoolToVisConverter}}">
The error message is indicating that the resource identified by the key BoolToVisConverter, to which you're trying to bind, cannot be found.
The most likely explanation is that you haven't declared that resource within a scope that can be accessed by your xaml. You'll want to create a StaticResource with a key matching the name you're referencing, within a Resources section of your xaml, the exact location may vary depending on your needs/structure.
Assuming you're doing this within a Window, you could do something like:
<Window>
<Window.Resources>
<BooleanToVisibilityConverter x:Key="BoolToVis"/>
</Window.Resources>
<Grid Visibility="{Binding isZoneTwoVisible, Converter={StaticResource BoolToVis}}">
<--...Content...-->
</Grid>
</Window>
Note: I haven't included your namespace in front of the BooleanToVisibilityConverter because this is a class which already exists within the framework.
It may be the case you require slightly different behaviour, or don't have access to that class, in which case you may need to add your namespace when defining the resource, e.g. <HelperObjects:BooleanToVisibilityConverter x:Key="BoolToVis"/>
Potentially useful further info about static resources: https://learn.microsoft.com/en-us/dotnet/framework/wpf/advanced/staticresource-markup-extension
Try to specify the converter in UserControlResources or even parent level Grid Resources. Assuming you are using a UserControl.
And your code is unclear as of where you are defining the StaticResource BoolToVisConverter. But generally heres the process.
Look at this sample code below to define your StaticResorce in the UserControl Resources section. Make sure you set the DataContext where isZoneTwoVisible is residing. I am hoping you implemented ImplementINotifyPropertyChanged and said PropertyChanged on your isZoneTwoVisible or isZoneTwoVisible is a DependencyProperty. Note: BooleanToVisibilityConverter is a class that implements an IValueConverter or if your property is a bool you don't even need that class.
<UserControl.Resources>
<BooleanToVisibilityConverter
x:Key="boolToVisibility"></BooleanToVisibilityConverter>
</UserControl.Resources>
You did all the things said above and it still dosen't work, sometimes I specify the relative Source hoping its residing in a UserControl.
Visibility="{Binding isZoneTwoVisible,Converter={StaticResource boolToVisibility},RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=UserControl}}">
Inside my WPF Application I am including a ResourceDictionary from another Project.
<Application x:Class="namespace.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<!-- This Line causes an Error -->
<ResourceDictionary Source="pack://application:,,,/Commons;Component/Generic.xaml" />
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
Metadata override and base metadata must be of the same type or derived type.
The solution builds successful and runs.
Restarting Visual Studio doesn't fix it.
Cut and Paste the <ResourceDictionary Source="..." /> line causes another error as explained here in the Comments:
Value Cannot be Null. Parameter Name: item. Restarting Visual Studio will then bring back the old error.
Sadly I haven't found out how to reproduce this error, I can only tell you something more about the environment im using:
Visual Studio 2015 Professional, Version 14.0.25431.01 Update 3
And allthough I doubt, those are associated with my problem, here my installed Plugins:
Resharper Ultimate 2017.1.1
GitExtensions Version 2.49.03
Sinatr's comment hinted me to read more about theming.
ThemeInfo
Inside of a Custom Control Library theres automatically created a ThemeInfoAttribute inside AssemblyInfo.cs
[assembly:ThemeInfo(
ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located
//(used if a resource is not found in the page,
// or application resource dictionaries)
ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located
//(used if a resource is not found in the page,
// app, or any theme specific resource dictionaries)
)]
Parameters
As it states in the autogenerated comments, the first parameter is to determine wheter there exist or where to find Theme specific resource dictionaries.
The second parameter defines wheter there exist or where to find the generic ResourceDictionary (Generic.xaml).
ResourceDictionaryLocation-Enumeration
The ResourceDictionaryLocation-Enumeration itself is used to specify the location of those dictionaries.
ResourceDictionaryLocation.None
No theme dictionaries exist.
ResourceDictionaryLocation.SourceAssembly
Theme dictionaries exist in the assembly that defines the types being themed.
This expects the ResourceDictionary to be located in a /Themes-Folder. Explanation later.
ResourceDictionaryLocation.ExternalAssembly
Theme dictionaries exist in assemblies external to the one defining the types being themed.
I am not going to explain how this works.
Why /Themes-Folder
Sadly I couldn't find too much about this. If someone has some more info please share.
Have you ever wondered, how styles of a lookless control are being applied?
If one created a lookless Control, he did as follows:
public class MyControl : ControlTemplate
{
static MyControl()
{
// This tells WPF to search for a Style for this type
DefaultStyleKeyProperty.OverrideMetadata(typeof(MyControl)),
new FrameworkPropertyMetadata(typeof(MyControl)));
}
}
In short, Ressources in WPF are located, by searching up the Logical-Tree, then inside Application's Resources and finally inside sth. they call System-Area (this is my translation from German, if you know a better one pls tell).
So depending on ThemeInfo, MyControl propably had its Style inside a ResourceDictionary inside the /Themes-Folder, eg. /Themes/Generic.xaml. And that tells WPF to add the Ressources to the System-Area which finally results in automatically resolving the appropriate style.
Somewhere inside /Themes/Generic.xaml:
<Style TargetType="{x:Type MyControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type MyControl}">
..
</ControlTemplate/>
</Setter.Value>
</Setter>
</Style>
That's why the above ThemeInfoAttribute requires Generic.xaml to be located in a /Themes-Folder. - And somehow, even if in my case the System-Area-Functionality isn't even used for this generic file, this causes those errors. But I wasn't able to find out why.
Sources:
ThemeInfoAttribute Constructor
ResourceDictionaryLocation Enumeration
Windows Presentation Foundation - Das Umfassende Handbuch, Rheinwerk Computing Version 4
In solving a problem around dynamic resources tonight, I ended up with a solution that relied on the ability of a Behavior class to participate in the resource hierarchy of it's associated framework element. For instance, consider the following
<Application>
<Application.Resources>
<system:String x:Key="TestString">In App Resources</system:String>
</Application.Resources>
</Application>
<Window>
<Window.Resources>
<system:String x:Key="TestString">In Window Resources/system:String>
</Window.Resources>
<Border>
<Border.Resources>
<system:String x:Key="TestString">In Border Resources</system:String>
</Border.Resources>
<TextBlock Text="{DynamicResource TestString}" />
</Border>
</Window>
The TextBlock will show the resource from the border. However, if I do this...
public void Test()
{
var frameworkElement = new FrameworkElement();
var testString = (string)frameworkElement.FindResource("TestString");
}
...it finds the one from the application because it is not part of the visual tree.
That said, if I instead do this...
public class MyBehavior : Behavior<FrameworkElement>
{
public string Value... // Implement this as a DependencyProperty
}
Then add it to the TextBlock like this...
<TextBlock Text="{DynamicResource TestString}">
<i:Interaction.Behaviors>
<local:MyBehavior Value="{DynamicResource TestString}" />
</i:Interaction.Behaviors>
</TextBlock>
The behavior does get the value of the resource and will track it dynamically. But how?
A Behavior is not a FrameworkElement so you can't call SetResourceReference on it, nor is it part of the Visual Tree so even if you could call SetResourceReference, it still wouldn't find resources local to the FrameworkElement. Yet that's exactly what a Behavior does. How?
Put another way, if we wanted to write our own class that also exhibited those same behaviors (no pun intended), how would one insert itself into the resource hierarchy of the visual tree?
Well, I think I found it! The secret is a Freezable. Simply put, when you add a Freezable to the resources of a FrameworkElement, any DependencyProperties on that Freezable which are assigned a DynamicResource will properly resolve.
Using this knowledge, I've created a DynamicResourceBinding that lets you use it like any other DynamicResource but with the added advantage of being able to specify a converter, format string, etc.
Here's a link to that page here on StackOverflow where I do this for both Dynamic and Static resources...
Post 33816511: How to create a DynamicResourceBinding
Is there any way to declare a top-level window as a content template in xaml and recreate it at load time? Essentially I'm trying to do something equivalent to data templating:
<DataTemplate DataType="{x:Type my:MyType}" >
<Window>
...etc...
</Window>
</DataTemplate>
This works fine at run-time but it generates an error at compile time due to the fact that you're not supposed to use a top-level window to a data template or style etc, so basically I need to replace DataTemplate with a custom class to get around this. I don't actually need support for DataType...data templates set the resource key implicitly to DataType but a bug in WPF means you can't use the relevant attribute on your own types. I can easily get around that by doing things in reverse i.e. specifying the type as the key:
<MyClass x:Key="{x:Type my:MyType}" >
<Window>
...etc...
</Window>
</MyClass>
What I need to know though is how to declare MyClass so that the XAML content generates a template that I can create instances from rather than an actual instance of the Window itself.
Is there a way to reuse a 3rd party control reference?
For example, I have this referenced in my App.xaml
xmlns:cust="clr-namespace:ThirdParty.Controls;assembly=ThirdParty.Controls"
I don't want to repeat this 3rd party control xml namespace on each page/control that needs a control from the library.
Is there anyway to centralize these references and use the prefix defined here? The possibility of each control having a different prefix is also worrisome. In asp.net you would put a reference in the web.config and it was available globally, I'm just looking to see if there is a similar method in WPF.
Two options I am thinking
1) Wrap that control into a UserControl and then use your UserControl in all the places.
2) Declare the third party control as a Resource somewhere and then use DynamicResource reference to that on your other places.
The second option can be implemented as bellow.
Where ever you want the third party control put a ContentControl like bellow
<ContentControl Template="{DynamicResource thirdPartyControlTemplate}" />
The ControlTemplate will be in the Resource file or at App.Xaml as bellow.
xmlns:thridParty="clr-namespace:WpfCustomControlLibrary1;assembly=WpfCustomControlLibrary1" >
<Application.Resources>
<ControlTemplate x:Key="thirdPartyControlTemplate" TargetType="{x:Type ContentControl}">
<thridParty:ThirdPartyControl />
</ControlTemplate>
</Application.Resources>
You can see that the namespace declaration will be always on this resource file and you will be able to use that Control control from any place
Take an example from the built-in control template for a Label:
<ControlTemplate TargetType="Label"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:s="clr-namespace:System;assembly=mscorlib"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
Show Me The Template is an amazingly helpful resource for these kinds of things. HTH