XAML Image Resource - c#

I add some pictures as ressource to my project (for example I put them into the folder "ressources").
Now I'm using them with:
<Image Name="_ImageName" Width="100" Height="100" Source="Resources\HalloPicA.png"/>
<Image Name="_ImageName" Width="100" Height="100" Source="Resources\HalloPicB.png"/>
... and so one.
Imagine now I will change the folder "Resources" to "MyResources". The Problem I have to change it everywhere in the XAML-code.
Is there a better way existing? In c#-Code I would declare a member variable from typ string like:
privat _FolderName = "Resources";
and use this member variable in this way:
Image newImage = Image.FromFile(_FolderName +"HalloPicA.png");
Hopefully my problems are clear.

You can use Property Binding and Value Converters to do this.
For example:
<Image Name="_ImageName" Width="100" Height="100" Source="{Binding Path=imgA, Converter={StaticResource imgPathConverter}}" />
Where your imgPathConverter is the class that can convert image name in your "qualified" image path.

What you can do is to create separate resource dictionary, or put it in Application.Resources, with BitmapImage resources:
<Application ...>
<Application.Resources>
<BitmapImage UriSource="/MyAssemblyName;component/MyPath/myImage.png" x:Key="imageKey"/>
</Application.Resources>
</Application>
and then when you want to use it
<Image Width="100" Height="100" Source="{StaticResource imageKey}"/>
this way when folder changes you'll need to change it only in one file

Related

Set image path as variable in the application resources of Avalonia for re-using

I have a logo, which is used in certain places of my application. So I'd like to store it's path in a variable of my App.axaml file, which should allow me to reference this path as variable in the entire application. This works fine with colors like StepBoxBG
<Application.Resources>
<Color x:Key="StepBoxBG">#5eba00</Color>
<Image x:Key="LogoPath">/Assets/Logos/logo.png</Image>
</Application.Resources>
which I reference using DynamicResource in e.g. a border element like this
<Border Background="{DynamicResource StepBoxBG}" Padding="20">
...
</Border>
But when my logo path is referenced in the same way
<Image Height="90" Source="{DynamicResource LogoPath}" />
no logo is displayed. The path is correct, because when I use the path directly in the Image element it works:
<Image Height="90" Source="/Assets/Logos/logo.png" />
I found this question and tried it, so the App.axaml looks like this:
<Application xmlns="https://github.com/avaloniaui"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="using:My.App"
xmlns:imaging="clr-namespace:Avalonia.Media.Imaging;assembly=Avalonia.Visuals"
x:Class="ULabs.Image2Card.App">
<Application.DataTemplates>
<local:ViewLocator/>
</Application.DataTemplates>
<Application.Styles>
<FluentTheme Mode="Light"/>
</Application.Styles>
<Application.Resources>
<Color x:Key="StepBoxBG">#5eba00</Color>
<imaging:Bitmap x:Key="LogoPath">
<x:Arguments>
<x:String>/Assets/Logos/logo.png</x:String>
</x:Arguments>
</imaging:Bitmap>
</Application.Resources>
</Application>
Now it throws an exception, because it refers this as an absolute path instead of being relative to the project:
System.IO.DirectoryNotFoundException: "Could not find a part of the path 'C:\Assets\Logos\logo.png'."
I set build action to AvaloniaResource so it should be included in my assembly. Also tried <x:String>Assets/Logos/ul-logo.png</x:String>, now the exception refers to the debug folder (bin/Debug/net5.0/Assets).
How can I specify a resource that just holds the /Assets/Logos/logo.png path and resolve it as hard-coded paths in the <Image> element would do?
You cannot use a Control subclass (Image) in <Application.Resources>. In WPF you would usually use a BitmapImage.
However, BitmapImage is not available in Avalonia, but you can resort to ImageBrush as an alternative, see this great example:
https://github.com/AvaloniaUI/Avalonia/issues/7211#issuecomment-998036759
Adapting the example only slightly to your use case, you could define Logo as follows in App.axaml:
<Application.Resources>
<Color x:Key="StepBoxBG">#5eba00</Color>
<ImageBrush x:Key="Logo" Source="/Assets/Logos/logo.png" />
</Application.Resources>
Finally, one would refer to it in this way:
<Image Height="90" Source="{Binding Source={StaticResource Logo}, Path=Source}" />

StaticResource Binding doesn't work as ImageSource

If I use this code:
<btn:Button ButtonImage="{Binding Path=BtnImage, FallbackValue=../Images/Search.png}"/>
my Button has a default image if BtnImage isn't set. When I try to change it into:
<UserControl.Resources>
<ImageSource x:Key="DefaultImage">
../Images/Search.png
</ImageSource>
</UserControl.Resources>
...
<btn:Button ButtonImage="{Binding Path=BtnImage, FallbackValue={StaticResource DefaultImage}}"/>
My default image isn't displayed. I want to understand why and how can I fix this because I am a fan of this StaticResource approach.
Edit:
My used Button is a dummy one:
<UserControl x:Class="WPF_Controls.Controls.Button"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Name="Btn">
<Button DataContext="{Binding ElementName=Btn}"
Command="{Binding Path=ButtonCommand}">
<Image Source="{Binding Path=ButtonImage}" />
</Button>
</UserControl>
Solution:
If I use:
<UserControl.Resources>
<system:String x:Key="DefaultImage">pack://application:,,,/DK_WPF_Controls;component/Images/Search.png</system:String>
</UserControl.Resources>
everything works as expected!
In case there is an "Images" folder in your Visual Studio project, which contains the "Search.png" file, and the file's Build Action is set to Resource, the following should work:
<UserControl.Resources>
<BitmapImage x:Key="DefaultImage" UriSource="/Images/Search.png"/>
</UserControl.Resources>
where
UriSource="/Images/Search.png"
is a XAML shortcut for a full Resource File Pack URI, i.e.
UriSource="pack://application:,,,<assembly name>;component/Images/Search.png"
Alternatively you can also use implicit conversion from string to ImageSource like
<ImageSource x:Key="DefaultImage">/Images/Search.png</ImageSource>

Why do my images show at designtime and not at runtime?

I have a WPF <Image> that I am trying to display on a <Button> inside of a <Toolbar> with the following code.
<ToolBarTray>
<ToolBar Height="26" Name="toolBar1" VerticalAlignment="Top" >
<Button Name="StampButton" Click="StampButton_Click">
<Image Source="/MyApp.Resources;component/Resources/MyImage.png"
Height="16" Width="16" Stretch="Fill"/>
</Button>
</ToolBar>
</ToolBarTray>
The image shows up just fine at design time. However, at runtime nothing is displayed. The resources are in another dll called MyApp.Resources. The button is actually created just fine and the click event works fine also.
Set your image build action to "Resource". Try to use full source path.
I was getting same problem - image displaying at design time, but not at runtime.
I had build action set to resource, tried different pack uris etc etc, but solution was simple
<Window.Resources>
<BitmapImage x:Key="your_image_key" UriSource="your_image.png" />
<Image Source="{StaticResource your_image_key}"/>
</Window.Resources>
This is what worked for me, from a site called wpf-tutorial.com:
<Image Source="/WpfTutorialSamples;component/Images/copy.png" />
Images is a subfolder of the project folder in my case, and I assume also in this sample.

Cannot assign geometry to Button clip property

I'm working on an interactive map. I'm using Silverlight 4 within VisualStudio 2010.
My problem is that I can't assign a geometry to Button Clip property:
Code:
bouton1.Clip = (PathGeometry)Forme.Data;
//forme is a class that inherits from Path
when I run my application I get an ArgumentException:
The value is not included in the expected range
Your Path called "Forme" has its geometry defined using the Path Mini-Language right?
This type of Geometry cannot be share by multiple elements.
The work-around is store the path data as a string in a ResourceDictionary accessible to both your "Forme" element and "bouton1" then assign it using StaticResource. Something like:-
<StackPanel>
<StackPanel.Resources>
<sys:String x:Key="MyPath">M 10,100 C 10,300 300,-200 300,100</sys:String>
</StackPanel.Resources>
<Button x:Name="btn" Content="Button" Height="150" Clip="{StaticResource MyPath}" />
<Path Data="{StaticResource MyPath}" Stroke="Black" StrokeThickness="2" />
</StackPanel>
The painful downside is that the VS2010 designer doesn't grasp this and therefore doesn't apply the path. You would need to run the app to visually see the results.
I changed button with Path and MouseLeftButtonDown event, it works :)

Why the Path and Polyline have different renderings in WPF?

Why the Path and Polyline have different renderings in WPF?
This is happening both in code and blend, maybe a I missing something or this
is just a anti aliasing effect.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="GeometryMonky.Window1"
x:Name="Window"
Title="Window1"
Width="640" Height="480" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" mc:Ignorable="d">
<Grid x:Name="LayoutRoot">
<Path Fill="#FFFFFFFF" Stretch="Fill" Stroke="#FF0000FF" Margin="100,10,0,0" Data="M289,39 L333,173" Width="1" HorizontalAlignment="Left" Height="100" StrokeThickness="1"/>
<Polyline Stroke="#FF0000FF" Margin="115,178,417,168" StrokeThickness="1" Width="100" Height="100">
<Polyline.Points>
<Point>10,0</Point>
<Point>10,100</Point>
</Polyline.Points>
</Polyline>
</Grid>
</Window>
Image sample from Blend:
http://img190.imageshack.us/img190/2965/wpfsmaple.png
Development system:
WinXP SP2, VS 2008 + SP1
It has to do with drawing modes of non-text objects. I tried setting the polyline object like the article linked below says and it does make it look just like the path.
So, short answer is it has to do with anti-aliasing. Here is the article: Single Pixel Lines
If you want the command here it is, give your polyline a Name and then add the following to the code behind.
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
// THIS IS THE LINE THATS IMPORTANT
pLine.SetValue(RenderOptions.EdgeModeProperty, EdgeMode.Aliased);
}
}
Your xaml change here:
<Polyline x:Name="pLine" Stroke="#FF0000FF" Margin="115,178,417,168" StrokeThickness="1" Width="100" Height="100">
<Polyline.Points>
<Point>10,0</Point>
<Point>10,100</Point>
</Polyline.Points>
</Polyline>
This will make your polyline object look just like your Path object. However changing the Path to use unspecified does not do anything so you can make your other objects look similar to the path but not vice versa.
Put this in your Path or Polyline xaml tag
RenderOptions.EdgeMode="Aliased"

Categories

Resources