I am attempting to set the image source in an effort to ultimately pull corporate standard images from what will be a DLL reference.
For testing and to ensure the proper syntax of the Uri, the image was loaded locally to a test project and the source was hard coded in the XAML.
<Image Name="imgTest" Source="pack://application:,,,/test2;component/Dictionaries/bricks.png"/>
The hardcoded value of imgTest.Source was viewed in debug mode and reads:
imgTest.Source = "pack://application:,,,/test2;component/Dictionaries/bricks.png"
Next, the source for the image was set in code.
BitmapImage imageUri = new BitmapImage();
imageUri.BeginInit();
var imageSource = new Uri(#"pack://application:,,,/" + Assembly.GetExecutingAssembly().GetName().Name + ";component/" + "Dictionaries/bricks.png", UriKind.Absolute);
imageUri.UriSource = imageSource;
imageUri.EndInit();
imgCopy.Source = imageUri;
The softcoded value of imgTest.Source was viewed in debug mode and reads:
imgTest.Source = "pack://application:,,,/test2;component/Dictionaries/bricks.png"
Both the hard coded and soft coded values are identical however the image does not render with the soft coded configuration.
Updates of the 'Build Action' property for the image have been attempted with Embedded Resource, Content, and Resource in combination with each of the three options available for the 'Copy to Output Directory' property.
Any wisdom on this issue is greatly appreciated.
Edit # 1
A side-by-side comparison where I copied the Source property to the soft coded image yields no image being displayed while the hard coded image does yet debug shows identical Source values. XAML and C# code shown.
<Image Name="imgCopy_Soft" />
<Image Name="imgCopy_Hard" Source="Dictionaries/bricks.png" />
imgCopy_Soft.Source = imgCopy_Hard.Source;
Edit # 2 Here is the full XAML
<UserControl x:Class="test2.ucConfigurator"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:test2"
mc:Ignorable="d" Height="439.5" Width="400">
<Grid >
<Grid.RowDefinitions>
<RowDefinition Height="32"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Row="0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="32"/>
<ColumnDefinition Width="32"/>
</Grid.ColumnDefinitions>
<Image Name="imgCopy_Soft" Grid.Column="0" />
<Image Name="imgCopy_Hard" Grid.Column="1" Source="pack://application:,,,/test2;component/Dictionaries/bricks.png" />
</Grid>
</Grid>
</UserControl>
And the code behind it:
namespace test2
{
public partial class ucConfigurator : UserControl
{
public ucConfigurator()
{
InitializeComponent();
}
public void Initialize()
{
BitmapImage imageUri = new BitmapImage();
imageUri.BeginInit();
var imageSource = new Uri(#"pack://application:,,,/" + Assembly.GetExecutingAssembly().GetName().Name + ";component/" + "Dictionaries/bricks.png", UriKind.Absolute);
imageUri.UriSource = imageSource;
imageUri.EndInit();
imgCopy_Soft.Source = imageUri;
imgCopy_Soft.Source = imgCopy_Hard.Source;
}
}
}
First, the DLL needs to be added as a References in Visual Studio:
I created a library project inside the same solution and named it _ImageLibrary. I then checked the box for it so it will be added to my project like so:
Inside the DLL, I set the image to this:
I have an image called awesome-cat.jpg. It is inside of a project directory called Resources.
I can then access it like so:
<Image Source="pack://application:,,,/ImageLibrary;component/Resources/awesome-cat.jpg"/>
REMEMBER!!! The portion of the XAML above shows the ASSEMBLY NAME and NOT the project name!!!! My assembly is ImageLibrary.dll.
Now if you HAVE the DLL as a loose file, just add it to your project and then reference that in References using the Browse feature.
It should be noted, this will only work if the DLL is shipped along side your exe. If you want to embed the DLL, then that is a whole different ball game and I can show you how to do that if you ask a separate question for it.
Related
I created an unpackaged WinUI 3 app based on this article: https://learn.microsoft.com/en-us/windows/apps/winui/winui3/create-your-first-winui3-app#unpackaged-create-a-new-project-for-an-unpackaged-c-or-c-winui-3-desktop-app.
The problem is that my window's XAML contains <Image Source="ms-appx:///Assets/Logo.png" />, and that Logo.png doesn't show in the window after publishing until I copy the image file to the Assets directory in the publish folder. But I don't want to keep images as separate files. I'd like them to be embedded in my build and to be accessed from XAML.
Whether it is realizable?
Based on Nick's link, I came up with the following solution:
class Loader: BitmapSource {
static readonly Assembly assembly = typeof(Loader).GetTypeInfo().Assembly;
public string Name {
set {
SetSource(assembly.GetManifestResourceStream(value).AsRandomAccessStream());
}
}
}
<Grid>
<Grid.Resources>
<local:Loader x:Key="Image1" Name="App1.Assets.Image.png" />
</Grid.Resources>
<Image Source="{StaticResource Image1}" />
</Grid>
The code above displays Assets\Image.png where App1 is the root namespace.
I have a derived devexpress grid control which sets some template for the indicator row:
<dxg:GridControl.Resources>
<sys:Double x:Key="{dxgt:TableViewThemeKey ResourceKey=IndicatorWidth, ThemeName=Office2016White}">300</sys:Double>
<DataTemplate x:Key="{dxgt:RowIndicatorThemeKey ResourceKey=RowTemplate, ThemeName=Office2016White}">
<Grid Name="IndicatorGrid">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="35" Name="IndicatorColumnRowNumber" SharedSizeGroup="RowNumberGroup" />
<ColumnDefinition Width="200" Name="IndicatorColumnDescription" SharedSizeGroup="DescriptionGroup" />
<ColumnDefinition Width="200" Name="IndicatorColumnSource" SharedSizeGroup="SourceGroup" />
</Grid.ColumnDefinitions>
//...
</DataTemplate>
</dxg:GridControl.Resources>
Right now the width of the indicator column is fixed to 300. Now I want the width of the row being calculated by the columns defined in the second part. I know I can access the indicator width of the view via the code behind as well but I'm not able to access the template controls in the code behind
var view = ((TableView)this.View);
view.IndicatorWidth = IndicatorColumnRowNumber.Width /* can not be found */ + ...
Since they live in the resources in the xaml. As I understand this is also not supposed to happen. What is the best way to implement this? Maybe extract the definitions in the code behind?
Edit:
Here is a picture of the table
I am not 100% sure what you are trying to achieve but if you want to access your resource in code behind you can go about it like this:
XAML:
<Grid x:Name="MyGrid">
<Grid.Resources>
<DataTemplate x:Key="MyResource">
<TextBlock Text="Hello"></TextBlock>
</DataTemplate>
</Grid.Resources>
</Grid>
Code behind:
public MainWindow()
{
InitializeComponent();
var resource = MyGrid.Resources["MyResource"];
var dataTemplate = (DataTemplate) resource;
}
You have additional tools to obtain any defined resources.
The methods FrameworkElement.FindResource and FrameworkElement.TryFindResource will search for resources from the element you specified and up the visual tree until the main application and including any themes you have setup. From the MS reference:
FrameworkElement.FindResource documentation
Also notice that the Resources dictionary and the FindResource methods accept an object key (not a string). This suits your case since your key is a RowIndicatorThemeKey object. You can instantiate such an object and set the ResourceKey property to the "RowTemplate" value and search for your resource like that.
In general solutions for problems such as yours can be achieved without requiring code behind though, if you provide some more information perhaps we can find a solution based on bindings.
I am currently trying to get an image to show in design time in my Xaml with the code below:
Xaml:
<Canvas Grid.ColumnSpan="2" Margin="0,0,0,0">
<Image Canvas.ZIndex="1" Source="{Binding Coupon.OverlayImage}" Margin="0,-21,-76,108" Stretch="Fill" x:Name="PrintImageContextMenu" />
</Canvas>
C# Design Time:
Coupon.OverlayImage = Image.FromFile(#"C:\Temp\Images\TestImage.png");
Original Property of OverlayImage in VB (Legacy Code):
private _overlayImage as Image
Public Property OverlayImage As Image
Get
Return _overlayImage
End Get
Set
_overlayImage = value
NotifyPropertyChanged("OverlayImage")
End Set
End Property
Upon first view I cannot see anything wrong with but it does not show, even at runtime. Any ideas would be appreciated.
You can use Image Fallback value to set the default image.Here is a simple example.
<Window.Resources>
<BitmapImage x:Key="ImageSource" UriSource="C:\Temp\Images\TestImage.png"/>
</Window.Resources>
<Grid>
<Image
HorizontalAlignment="Left"
Source="{Binding SourceImage,FallbackValue={StaticResource ImageSource}}"/>
</Grid>
Everywhere you use the Image class, I think you use the System.Drawing.Image because the WPF Image control does not have a FromFile() method . You cannot use it as a source for the WPF Image Control. You must instead try using an IValueConverter to convert the Image to a BitmapSource/ImageSource.
Try this,
var uri = new Uri(Coupon.OverlayImage);
var bitmap = new BitmapImage(uri);
ImageName.Source = bitmap;
I have a class library written in C# for Windows 8 with a custom control and a folder called Images with bunch of images in it. In control template I have an image
<ControlTemplate TargetType="local:MyCustomControl">
<Grid Background="Transparent">
<Image x:Name="MyImage"
Height="{TemplateBinding Height}"
Width="{TemplateBinding Width}"
Stretch="Fill" />
...
</Grid>
</ControlTemplate>
I want to set in this control's code-behind one of that images (which are inside this class library) as a source for this image.
What I have already tried:
Absolute uri using FrameworkElement.BaseUri with both Do Not Copy and Copy Always property values of images:
this.MyImage.Source = new BitmapImage(new Uri(this.BaseUri, imagePath));
Relative uri with both Do Not Copy and Copy Always property values of images:
this.MyImage.Source = new BitmapImage(new Uri(imagePath, UriKind.Relative));
ms-resource uri scheme.
How can I achieve it?
Ok, that escalated quickly. :) Maybe, will be useful for others.
The solution is to use assembly name of the library in the path:
var assemblyName = this.GetType().GetTypeInfo().Assembly.GetName().Name;
this.MyImage.Source = new BitmapImage(new Uri(this.BaseUri, assemblyName + imagePath));
So I am wondering where the relative uri should be set relative to. I had assumed it was the main project.
I have the image stored under a folder images. The images folder is directly under the project DaedalusGraphViewer under the solution which also has the same name (DaedalusGraphViewer).
I had assumed that the relative uri was relative to the project, but I don't seem to be having any luck. Alternative ideas such as doing it from code behind are also welcome. I have done it from code behind before so I can probably figure that out since I will be able to debug it better there, but I would prefer to just do it in xaml.
I am using
<ResourceDictionary Source="DaedalusGraphViewer/ResourceDictionaries/GraphViewerBrushes.xaml" />
to do the same thing elsewhere, so I don't see what I'm doing wrong.
<Button
Height="50"
VerticalAlignment="Top"
>
<Image Width="50" Height="50" Source="Images/zoominbutton.bmp" Stretch="Fill"/>
</Button>
edit: still no luck, not sure what I'm doing wrong.
i've revised the code to use a much smaller test case.
ideally i would like to be able to set the image path from xaml, but for now i'm trying code behind just to see if I can figure out anything that will make it work.
<Window
x:Class="TestApp.Window1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="Window1" Height="300" Width="300"
Loaded="Window_Loaded"
>
<Canvas x:Name="MainCanvas">
<!--<Image x:Name="ImageSource2" Width="50" Height="50" Source="/DaedalusGraphViewer;component/images.jpg" Stretch="Fill"/>-->
<!--<Image x:Name="imagetest" Stretch="Fill" Width="50">
<Image.Source>
<BitmapImage
DecodePixelWidth="200"
UriSource="/Images/images.jpg"/>
</Image.Source>
</Image>-->
<!--<Image Width="50" Source="../../Images/images.jpg" Stretch="Fill"/>-->
</Canvas>
</Window>
namespace TestApp
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
Image i1 = new Image();
Uri relativeuri = new Uri("/DaedalusGraphViewer;component/images.jpg", UriKind.Relative);
BitmapImage bmi = new BitmapImage(relativeuri);
i1.Source = bmi;
MainCanvas.Children.Add(i1);
}
}
}
My goal for now is just to display an image on the main canvas. When do I need to use an absolute uri and when can I use a relative Uri. I have read lots of examples of xaml using relative uris so I thought that would be possible.
Replace YOURAPPNAME
<Image Width="50" Height="50" Source="/YOURAPPNAME;component/Images/zoominbutton.bmp" Stretch="Fill"/>
I got it to work using "pack://application:,,,/images.jpg" as the source. However, I'm still confused as to why I can't get a relative pack uri to work like this:
http://msdn.microsoft.com/en-us/library/aa970069.aspx
I thought I could just use a source = "/images.jpg"
I read elsewhere that there is a default string to uri converter that converts the relative uri to an absolute uri based on the assembly being built.
anyway if anyone knows how to get the relative pack uri to work or why it doesn't work, please let me know.
I also got ebattulga's answer to work, so I'm selecting it as the right answer. However, I would like to understand a bit better why the relative pack uri from the pack uri site doesn't work.
ps - It doesn't appear to work with the image set to content. I got it working with the image build type set to resource
ps2- I haven't been able to get the same code to work with .bmp extension images. Not sure what is going on.