Accessing resource in WPF - c#

I know this is simple but I am very new in XAML.
I have two folders in my solutions
Resources\Images\font.png
Shapes\dictonary1.xaml
the soultion also has app.xaml and mainwindow.xaml
<Label ToolTip="Label">
<Label.Background>
<ImageBrush ImageSource="\Resources\Images\Font.png" />
</Label.Background>
</Label>
In my dictonary1.xaml file I add a label containing a background brush
But throws me an error
This work fine in wen I do the same in MainWindow.xaml file.
The font.png file properties
Build action is Resource and
Copy to output directory is always Copy always
I hope I am clear

Did you merge dictionary1.xaml into the mainwindow.xaml? If the image is used in dictionary1.xaml then try this:
<ImageBrush ImageSource="../Resources/Images/Font.png" />

Related

How to use resources (fonts, images, styles) from external library

I'm having problems with loading resources (images, font families, styles) from an external resource dll. I would like to have all resources (images, fonts, styles...) in one resource dll and set them to be accessible over all projects (libraries) in this solution. Those projects in solution are different libraries that are referenced and called by main application.
So far i tried several different propositions how to do it but none of them work.
I'm using Visual studio 2019 and compiling for .net 4.6.2 - if that means something...
First I created an resource library called myapp.resources. Inside this project I have a folder named Fonts and inside that folder is the Lato-Thin font.
Also at the root of the project I created a resource dictionary called Fonts.xaml
-Project
-Fonts
-Lato-Thin.ttf
-Fonts.xaml
the structure of the Fonts.xaml:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:myapp.resources">
<FontFamily x:Key="LatoThin">Fonts/#Lato Thin</FontFamily>
</ResourceDictionary>
In the main app App.xaml I added the loading of that ResourceDictionary:
<ResourceDictionary x:Key="Dict">
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="pack://application:,,,/myapp.resources;component/Fonts.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
The last step is adding this fontfamily to label control:
<Label Grid.Row="0" Grid.Column="0" Content="some random text for test" FontFamily="{StaticResource ResourceKey=LatoThin}"/>
But I always get the error that the LatoThin font resource can't be located.
The same error I get with any other resource type like images, styles.
Of course I added the references to projects and every file is where it should be.
The only thing that is working is, for example adding image to buttons in this way.
<syncfusion:ButtonAdv x:Name="btnSelectFile"
Grid.Row="1" Grid.Column="2"
VerticalAlignment="Center" SizeMode="Small"
Height="26" Width="26" Label="Button" Margin="3,3,3,3"
SmallIcon="pack://application:,,,/myapp.resources;component/Images/add.png"/>
I tried to find some complete tutorials to follow but I always have the same error.
So, my question would be: How to solve this?
Thanks for any advice.
Make sure your font file (Lato-Thin.ttf) has its build action set to Resource.
In your Fonts.xaml make sure to use this format:
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:myapp.resources">
<FontFamily x:Key="LatoThin">/myapp.resources;component/Fonts/#Lato Thin</FontFamily>
</ResourceDictionary>
Tip: You can remove pack://application:,,, from your URIs to make them shorter.

Using vector graphics from Inkscape in WPF in a resource effective matter

This question aims to be a best practice on how to use images created with Inkscape and saved as XAML.
There are many articles on the internet but not many of them show the pro and cons of each solution. Example 1, Example 2
When you create an image with Inkscape and save as XAML you'll only have a Viewbox inside an XAML.
<?xml version="1.0" encoding="UTF-8"?>
<!--This file is NOT compatible with Silverlight-->
<Viewbox xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" Stretch="Uniform">
<Canvas Name="svg8" Width="210" Height="297">
<Canvas.RenderTransform>
<TranslateTransform X="0" Y="0"/>
</Canvas.RenderTransform>
<Canvas.Resources/>
<!--Unknown tag: sodipodi:namedview-->
<!--Unknown tag: metadata-->
<Canvas Name="layer1">
<Rectangle xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Canvas.Left="55.184521" Canvas.Top="113.30357" Width="33.261906" Height="33.261906" Name="rect4485" Fill="#FFFFFFFF" StrokeThickness="5.29166651" Stroke="#FF000000" StrokeMiterLimit="4"/>
</Canvas>
</Canvas>
</Viewbox>
To use this file I'd normally have to wrap it in a ResourceDictionary. This is annoying because I cannot edit the file in Inkscape anymore without having to remove the ResourceDictionary before.
The image will be shown multiple times, for example in a ListViewItem or any other element that has an ItemsSource.
Is there a way to have only one ResourceDictionary where I can import all of these XAML files?
Let's assume I have wrapped it in a ResourceDictionary and given the Viewbox a x:Key="SquareIcon" value.
What is most resource effective way of showing this element?
Should I use a ContentPresenter and set its Content property and set the Canvas x:Shared="false"?
Is it more effective to use a Label (or some other control)?
Maybe remove the Viewbox and always use the Canvas in a Viewbox in my own view?
Should I wrap the Viewbox in a ControlTemplate and use it in ContentPresenter Template property? This way I don't need to use the x:Shared attribute on Canvas.
When saving an asset from Inkscape as xaml, you can copy it to Blend and then convert it to Path. Then you have a vector representation of that asset, which you can easily incorporate as a style.
You can read about converting to path here
Keep in mind that you can also combine several elements and then convert them. Basically, any kind of image that is in one color can be converted to a single path.
As far as best practice goes, I like to keep all of my Path/Image/Icon related styles in a single ResourceDictionary and then reference it globally in App.xaml file.
I think you can create it manually by reading all your files. Steps are next:
1) You have your resources in your project with xaml or svg
2) Create your markup extension which will provide a value of Geometry by a path of your embedded resource file with an icon. (it should parse and provide value)
3) Create a custom control IconControl for displaying icons with dependency property IconPath (String) and bind it in your template by template binding
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:IconControl">
<Viewbox ><!--Could be other container -->
<Path Data="{TemplateBinding IconPath}"
Fill="{StaticResource DefaultBrush}" />
</Viewbox>
</ControlTemplate>
Viewbox isnt so good, because it applies transformations to content. So you should use simpliest container to achive good performance.
4)Use your control in markup
<IconControl IconPath={locl:IconSvgMarkupExtension PathToYourEmbededResourceHere}/>
I wrote it without VS, from memory, so there could be some mistakes.
Should I wrap the Viewbox in a ControlTemplate and use it in
ContentPresenter Template property? This way I don't need to use the
x:Shared attribute on Canvas.
It is also a possible case, a few years ago I've used the same approach without so each of my icons was ContentControl with different Template for it depending on Icon.
I had a similar issue : Inkscape svg saved as XAML does not work for me.
After some long search I found this very quick but useful video on Youtube :
https://www.youtube.com/watch?v=otEV-skBqyI
combine with the converter available on Github here : https://github.com/BerndK/SvgToXaml
used to convert svg to a DrawingImage ressource
(available thanks BerndK)
It solves my issue !
Just then have to save the ressource file as .xaml in my project
content of Xaml file
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DrawingImage x:Key="MyVectorImageName">
<DrawingImage.Drawing>
<DrawingGroup ClipGeometry="M0,0 V297 H210 V0 H0 Z">
.... //this part is the DrawingImage content Iget in converter and I copied pasted
</ResourceDictionary>
And to use it :
<Grid x:Name="gridImage" Margin="0,62.8,0,0" >
<!-- Add vector ressource and display it -->
<Grid.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="images/MyVectorImageName.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Grid.Resources>
<Image x:Name="imgName" Source="{StaticResource MyVectorImageName}"/>
</Grid>
Note : I added it as a local ressouce not a global one (but i is possible too)

Unable to see image masked over the button

I write the following code to show image over the button but when i run the project it is not displaying anything.
<Button x:Name="Employee">
<Button.Template>
<ControlTemplate>
<Border HorizontalAlignment="Center" VerticalAlignment="Center" >
<Image Source="images/Employee.png"
Width="50"
Height="50"/>
</Border>
</ControlTemplate>
</Button.Template>
<TextBlock>Add New Epmloyee</TextBlock>
</Button>
The relative path is correct? The folder "images" must be located in the same folder where the Window's XAML is saved.
Ensure that the Build Action for file "Employee.png" is "Resource".
I just tried your xaml code and it works fine. please make sure that you have images folder under your root directory and an image below it with name employee.png
Finally i nail the problem. The problem was that i create the folder by going directly to project folder through My Computer that's why it was not showing in Visual studio. Now I add the folder from VS and drag the images in it. And Woah! it works fine. Thanks to all of you.

Import separate XAML as ResourceDictionary and assign x:Key

I downloaded the Visual Studio Image Library and I see that the included icons are available in vector format in the form of .XAML files. Here is an example:
Add_16x.xaml
<!-- This file was generated by the AiToXaml tool.-->
<!-- Tool Version: 14.0.22307.0 -->
<Viewbox Width="16" Height="16" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
<Rectangle Width="16" Height="16">
<Rectangle.Fill>
<DrawingBrush>
<DrawingBrush.Drawing>
<DrawingGroup>
<DrawingGroup.Children>
<GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" />
<GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M5.0004,-0.000199999999999534L5.0004,4.9998 0.000399999999999956,4.9998 0.000399999999999956,10.9998 5.0004,10.9998 5.0004,15.9998 10.9994,15.9998 10.9994,10.9998 16.0004,10.9998 16.0004,4.9998 10.9994,4.9998 10.9994,-0.000199999999999534z" />
<GeometryDrawing Brush="#FF388A34" Geometry="F1M10,6L15,6 15,10 10,10 10,15 6,15 6,10 1,10 1,6 6,6 6,1 10,1z" />
</DrawingGroup.Children>
</DrawingGroup>
</DrawingBrush.Drawing>
</DrawingBrush>
</Rectangle.Fill>
</Rectangle>
</Viewbox>
I want to put all the icon xaml files I want to use in my application source in a folder called "Icons" and then be able to have a file called IconDictionary.xaml somewhere else that defines a ResourceDictionary holding a MergedDictionaries and inside this MergedDictionaries I want to be able to include the icon.xaml files somehow and assign them an x:Key property so I can refer to them throughout my application as static resources.
Is it possible to use this icon.xaml file without modifying the .xaml file itself?
I would like to be able to just leave them as they are but unfortunately it seems like I have no choice but to either copy their contents into my IconDictionary.xaml or edit the individual .xaml files and surround them in a ResourceDictionary with a x:Key that I could add to my MergedDictionaries.
UPDATE
Here is what I would like my IconDictionary.xaml to look like for clarity:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DataTemplate x:Key="Add_16x">
<!-- Import Viewbox from Add_16x.xaml here... -->
</DataTemplate>
</ResourceDictionary>
Is it possible to use this icon.xaml file without modifying the .xaml file itself?
I don't believe so. While XAML looks a lot like XML, and follows a lot of XML rules, the XAML compiler doesn't seem to allow the DOCTYPE and ENTITY markup that would normally be used to import XML from one file into another. When used, the first error reported reads "DTD is prohibited in this XML document". Without the ability to provide a DTD, you can't declare entities, and thus won't be able to import the standalone XAML.
If you want to use the generated XAML file directly, you can add the file to your project as a Resource. The resource data can then be loaded using XamlReader.Load() in code-behind, added at the appropriate time where you want it.
For example, assuming you have copied the XAML file to a folder named "Resources" in your project, and set the "Build Action" for the file to "Resource", you can write code like this to retrieve the object:
using (Stream stream = App.GetResourceStream(
new Uri("pack://application:,,,/Resources/Add_16x.xaml")).Stream)
{
object o = XamlReader.Load(stream);
}
That will get a Stream object representing the XAML file data that has been embedded in your application and then load the WPF object the XAML represents, using the XamlReader.Load() method.
Personally, when I am using these files, I just copy/paste the DrawingGroup element from the XAML file, into my own resource XAML file. The wrapper (Viewbox, Rectangle, and DrawingBrush) are all redundant anyway. What I really need is the DrawingGroup object.
When I do this, I also remove the explicit <DrawingGroup.Drawing> syntax, and just include the children of the DrawingGroup directly, making the XAML a bit more concise. E.g.:
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<DrawingGroup x:Key="Add_16x">
<GeometryDrawing Brush="#00FFFFFF" Geometry="F1M16,16L0,16 0,0 16,0z" />
<GeometryDrawing Brush="#FFF6F6F6" Geometry="F1M5.0004,-0.000199999999999534L5.0004,4.9998 0.000399999999999956,4.9998 0.000399999999999956,10.9998 5.0004,10.9998 5.0004,15.9998 10.9994,15.9998 10.9994,10.9998 16.0004,10.9998 16.0004,4.9998 10.9994,4.9998 10.9994,-0.000199999999999534z" />
<GeometryDrawing Brush="#FF388A34" Geometry="F1M10,6L15,6 15,10 10,10 10,15 6,15 6,10 1,10 1,6 6,6 6,1 10,1z" />
</DrawingGroup>
</ResourceDictionary>
You can then use the above resource however you like. For example, an idiomatic approach in WPF would be to declare a DataTemplate configured to display a Drawing the way you want, and then bind a given Drawing resource as the content for a content control. E.g.:
<DataTemplate DataType="{x:Type Drawing}">
<Rectangle>
<Rectangle.Fill>
<DrawingBrush Drawing="{Binding}" Stretch="Uniform"/>
</Rectangle.Fill>
</Rectangle>
</DataTemplate>
Then elsewhere:
<Button Content="{StaticResource Add_16x}"/>
(Making sure the style for the content control, e.g. your Button, is otherwise compatible with your Drawing resource, i.e. correct size, etc.)

embed project icon in WPF

This problem is getting me crazy, I really have no clue what's going on - why it's not working as I think it should.
I have a WPF C# project. I've added a directory named "ExtFiles" to my solution. This directory contains a ICO file, a PNG image and TTF font.
All three files have "build action" set to "resource", and "copy to output dir" set to "Do not copy".
I call these 3 files in the XAML via:
For the Icon:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" x:Class="Swiftech_Imperium.MainWindow"
Title="Imp" Height="435" Width="510" ResizeMode="CanMinimize" WindowStartupLocation="CenterScreen" Icon="pack://application:,,,/ExtFiles/imp.ico"
For the Image:
<Image HorizontalAlignment="Left" Width="278" Height="30" Margin="9,401,0,0" VerticalAlignment="Top" Source="pack://application:,,,/ExtFiles/Logo.png"/>
And for the font:
<Label x:Name="LabelTemp1" BorderBrush="#FFFFA421" BorderThickness="1" FontFamily="pack://application:,,,/ExtFiles/#DS-Digital" Height="30"
Everything works, no error. The image is displaying, the icon too, the font is working.
But, when I publish, it does generate the ExtFile directory with the icon in it. Why is that? My goal is to have all 3 files embedded in the EXE. My goal is deploy the program using the single EXE file and nothing else, as the users's requirement.
All these 3 files are called only in the XAML and nowhere else, I don't understand why it's working fine for the image and font but not for the icon...
Any idea?
Thanks
Steve
Edit: I tried this: Embed multiple icons in WPF EXE (last answer) but it doesn't work.
Icon="/Resources/Imp.ico"
Source="/Resources/Logo.png"
FontFamily="/Resources/#DS-Digital"
I get this error (only for the icon, If I can the Icon=".." out it starts but the image and the font are not applied...
'System.Windows.Baml2006.TypeConverterMarkupExtension' threw an exception.' Line number '5' and line position '9'.
I added the 3 files as resources (Resource, add file) and set their build action to "resource".
edit:
OK... I moved forward a tiny bit.
I added both DLL's (yeah there two!) to the resources.
Moved the image/icon/font to a separate folder (that probably wasn't needed).
but I was still getting the same error (parsing).
turns out it is my XAML that is calling the second DLL (which I originally forgot to add to the resources).
Now with both DLL's as resources, if I go into References and set both of these DLL's Copy Local to False, I get an error. I can put the first dll (WPFToolkit.dll) to false, but I can't do for system.windows.controls.datavisualization.toolkit.dll :(
reason why is because the XAML is calling it:
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:chartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit" x:Class="Imperium.MainWindow"
Title="Imperium" Height="435" Width="510" ResizeMode="CanMinimize" WindowStartupLocation="CenterScreen" Icon="pack://application:,,,/ExtFiles/Imp.ico" Closing="Window_Closing" MouseDown="Grid_MouseDown" WindowStyle="None" BorderThickness="1" BorderBrush="Black" Foreground="Black">
what can I do?
Your pack URN was wrong for the icon. It should be:
pack://application:,,,/(qualified assembly name i.e. My.Project.Executable);component/ExtFiles/imp.ico
When you add the file to the VS project folder you should set it as Resource with Do Not Copy.
The same applies for the image and the font - tho' I would also say that I've not loaded font using a direct reference like this and I'm not sure it works like this.
Try This:
Doing with Resources would be a different approach to achieve the same task. I would like to provide you a link to read certain msdn articles.
Adding and Editing Resources (Visual C#)

Categories