.NET 6 - WPF CustomControl Template not applied though being in App Resources - c#

We are switching a huge WPF Appl. to .NET 6.0. At least one CustomControl which worked on 4.8 does not get it's template applied which is referenced via Generic.xaml. I am not sure if Generic.xaml is not loaded or something else needs to be considered.
The Style can be added manually to Application.Resources.MergedDictionaries via a simple "Add" call with the Source set to it. I can see the CustomControl Style afterwards with the Key being the correct Type. It is still not applied, as there is no visual representation and no call is made to the overriden OnApplyTemplate method.
If all else fails, can I apply a template manually if I have the given style, like just apply the Style manually to a newly created instance?
Also: the Projects are now SDK-Style, AssemblyInfo.cs was taken over and "generate assembly info" is set to false. It contains the standard ThemeInfo entry.
Just for clarification following the code which successfully finds the Generic.xaml. But before 6.0 Generic.xaml was loaded without doing anything.
Application.Current.Resources.MergedDictionaries.Add(new ResourceDictionary
{
Source = new Uri("/Contracts;component/Themes/Generic.xaml", UriKind.Relative)
});
Thank you all for your help!

I had the same Problem.
maybe u need to add the Assembly.cs at TopLevel of ur CustomControlLibrary
using System.Windows;
[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)
)]

Related

Xamarin: How do I apply the following android theme to my activity at runtime?

I have the following activity which specifies the theme as an attribute
[Activity(Label = "PermissionsActivity", Theme = "#android:style/Theme.Translucent.NoTitleBar")]
public class PermissionsActivity: Activity
This works well, but how can I apply the same at runtime? Maybe by calling SetTheme in OnCreate. I can see SetTheme accepts a resource id integer. I'm having a hard time finding the corresponding Xamarin.Android constant for the aforementioned theme. Please help
Add your theme in style.xml file under Resource folder than access it from resource as int
<style name="MyTheme" parent="Theme.Translucent.NoTitleBar">
</style>
Setting in activity
this.SetTheme(Resource.Style.MyTheme);
Add this code in your onCreate Method:
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Call setTheme before creation of any(!) View.
setTheme(android.R.style.Theme_Dark);
// ...
setContentView(R.layout.main);
For reference check this Link
When you add some theme in any folder under the resources of an android project what Visual studio does is it creates a corresponding int value inside the ResourceDesigner.cs file under the resources folder.
Now in Runtime when you need to add these to your code they are available as follows:
If the resource is a style then it is available in Resource.Style.YourResourceName
If the resource is a dimension then it is available in Resource.Dimen.YourResourceName
If the resource is a string then it is available in Resource.String.YourResourceName
If the resource is an image under the drawable folder then it is available in Resource.Drawable.YourResourceName
If the resource is an image under the mipmap folder then it is available in Resource.Mipmap.YourResourceName, And so on and so forth.
Note: These properties are always an integer.
In your case since it is a theme(which is basically a style)
Hence you can get it like this in an Activity:
this.SetTheme(Resource.Style.MyTheme);
And in a Fragment something like this :
this.Activity.SetTheme(Resource.Style.MyTheme);
Hope this helps,
Revert in case of queries.

GTK+ Glade and CSS

I've made a simple glade UI file for my programm. It contains of 2 textfields and 1 button. And also I made a css style which contains 1 button class named "button". When I added this file in Glade as "Custom CSS provider" it changed my button style within the editor.
After that I created the UI using GtkBuilder (I am using GTK# 3.20 bindings + C#).
Builder b = new Builder ();
b.AddFromFile ("login.xml");
b.Autoconnect (this);
It created my simple form (2 fields and 1 button) but there is no CSS Style applied to it. So I checked XML code of my UI file and found out that there is no reference to CSS exept of this:
<style>
<class name="button"/>
</style>
After that I read that I need CssProvider. So I created one.
CssProvider css = new CssProvider ();
css.LoadFromPath ("ui_common.css");
But nothing happened. So, how should I apply custom CSS to my Builder UI?
You are almost there; the last step is to take the GtkCssProvider and add it to a GtkStyleContext.
Since you are using a .ui file and a .css file, I assume you want to make your CSS apply to all widgets in the application. In that case, you can use gtk_style_context_add_provider_for_screen(), passing gdk_screen_get_default() as the GdkScreen. (This should be safe; it's what the GTK+ Inspector does. IIRC there was a more specific reason why this should be safe...)
You can also do this to individual widgets using gtk_widget_get_style_context() and gtk_style_context_add_provider().
In both cases, use GTK_STYLE_PROVIDER_PRIORITY_APPLICATION as the priority for application-local CSS.
(I do not know the C# names; sorry.)

Accessing resources from code for setting NotifyIcon.Icon

I am trying to get the Icon of a NotifyIcon in WPF.
So I have added a .ico file to my solution in a Resources folder and set the build action to Resource.
I am trying to grab this resource in code behind like so:
var icon = (Icon) Application.Current.FindResource("/Resources/icon.ico")
This doesn't work.
In addition to this: Application.Current.Resources.Count returns 0.
EDIT
var i = new Icon(Application.GetResourceStream(new Uri("/systemtrayicon.ico", UriKind.Relative)).Stream);
With the icon in the root and the build action set to Resource.
Still not working.
EDIT AGAIN:
I needed to Clean the solution and rebuild as per: WPF throws "Cannot locate resource" exception when loading the image
This will works 100%
ni.Icon = new Icon(Application.GetResourceStream(new Uri("pack://application:,,,<Image Location From root>")).Stream);
Example:
notify.Icon = new Icon(Application.GetResourceStream(new Uri("pack://application:,,,/images/favicon.ico")).Stream);
You have to pass resourceName as a parameter to the FindResource method, not the path for the Resource. Sample code would look like:
var icon = (Icon) Application.Current.FindResource("myImage")
Please note in the above sample code "myImage" is the resource name.
Refer to Application.FindResource Method on MSDN.
You say, Application.Current.Resources.Count is Zero, that means you do not have any Resource defined in your App.xaml file.
You can add resources to App.xaml like this:
<Application.Resources>
<Image x:Key="myImage" Source="img.png" />
</Application.Resources>
It appears that your icon is an embedded resource. FindResource cannot work with embedded resources. Set BuildAction of your icon to Resource.
Refer to this MSDN page for more reading on WPF Resources.
UPDATE
Code for accessing Embedded Resources
Assembly.GetExecutingAssembly().GetManifestResourceStream("myImg.png");
However, if you had added this image to the Resources.Resx and you should simply be able to use Resources.ResourceName.
UPDATE 2
Adding resources to App.xaml or any ResourceDictionary is better, so that you can use them as Static/Dynamic resources via StaticResource or DynamicResource markup extensions.
If you do not want to add it to App.xaml resources and still want to access it, one option as I mentioned above is to add it to the Resources.Resx and use Resources.ResourceName to refer the icon/image
Another way is to create System.Drawing.Icon by yourself, sample code:
new System.Drawing.Icon(Application.GetResourceStream(new Uri("/Resources/icon.ico")));
Personally, I would go with XAML resources and add them to App.xaml or a ResourceDictionary.

Acessing WPF XAML Resources from non-WPF code

I am currently building an application that consists of several components, each of which is essentially a WPF user control with a little C# code around it for the plugin system to work (using MEF).
The problem I am having is that each component should include an icon and for niceness purposes I defined that as a System.Windows.Media.Brush so I can just use the DrawingBrush exported from Design there. Now I need to access that piece of XAML from non-WPF C# where I currently have the horrible workaround of instantiating the user control and asking it for the resource:
private Brush CachedIcon = null;
public override Brush Icon
{
get
{
if (CachedIcon == null)
{
CachedIcon = (Brush)(new BlahControl().TryFindResource("Icon"));
}
return CachedIcon;
}
}
I couldn't find a way to read that resource (which is a .xaml file, and referenced in a ResourceDictionary in the custom control) from a "normal" C# class. Anything belonging to WPF has that nice TryFindResource method but how to do that otherwise? I don't want to have the XAML file with the icon lying around un-embedded.
In your XAML code make sure the icon resource has the build option set to "Resource", and then reference the resource to make it a xaml static resource
<UserControl.Resources>
<BitmapImage x:Key="icon1" UriSource="Resources/Icon1.ico" />
</UserControl.Resources>
Then in your .Net 2.0 code you will find the resource in the "{xamlName}.g.resource" stream
Example code that loads all icons from a xaml dll into a dictionary:
using System.IO;
using System.Reflection;
using System.Collections;
using System.Resources;
...
var icons = new Dictionary<String, Bitmap>();
var externalBaml = Assembly.LoadFile(Path.Combine(Environment.CurrentDirectory, "MyXaml.dll"));
Stream resourceStream = externalBaml.GetManifestResourceStream(externalBaml.GetName().Name + ".g.resources");
using (ResourceReader resourceReader = new ResourceReader(resourceStream)) {
foreach (DictionaryEntry resourceEntry in resourceReader) {
if (resourceEntry.Key.ToString().ToUpper().EndsWith(".ICO")) {
icons.Add(resourceEntry.Key.ToString(), Image.FromStream(resourceEntry.Value as Stream) as Bitmap);
}
}
}
My suggestions are:
Provide metadata on your control about where the icon can be found. You can do this with your own custom attribute (see example 1 below). This metadata will allow you to load the icon without creating an instance of the control.
Since you're using MEF, you can use metadata in your export to achieve the same as above. Details here. See example 2 below.
Treat your icon as an ImageSource rather than a Brush. You can use WPF's Image control to show your ImageSource, or you can paint it with an ImageBrush.
Use the technique provided by TFD to read the resource with the name specified in the metadata. Unfortunately, WPF does not appear to provide anything like a BamlReader, which would make it much cleaner to load the WPF resource from a non-WPF context.
Example 1:
[Icon("MyIconResourceName")]
public class BlahControl : Control
{
...
}
Example 2:
[Export(typeof(IApplicationComponent))]
[ExportMetadata("IconResource", "MyIconResourceName")]
public class BlahControl : Control
{
...
}
You can read resources from your assembly as stream.
Example code here:
http://www.wpftutorial.net/ReadWPFResourcesFromWinForms.html
Define the icons at the app level instead of in the control, either in the app.xaml or a master resource dictionary xaml file. Then you can use the same TryFindResource method, but without creating an instance of the control.

Using string resources from UserControl resource file

I'm trying to add string resources to my UserControl. I have created a new UserControl and when I try to edit the automatically created mycontrol.resx file I'm met with this message:
You are trying to edit a resource file that is a poart of another project item (such as a form or a control). Editing this item could corrupt the project item, and you will have to recover it by hand. In addition, changes made to this resource file may be lost if further chagnes are made to the project item.
Do you really want to edit this file?
If I accept and continue, I can't access the strings through mycontrol.MyString unless I change the resource file access modifier to public (default is "no code generation") but then the project doesn't compile and shows these errors:
Missing partial modifier on declaration of type mycontrol; another partial declaration of this type exists
Type mycontrol already defines a member called '.ctor' with the same parameter types.
Thanks

Categories