How do I share an image among WPF projects? - wpf

I have a solution with a number of WPF projects and UserControls in those. Among these is a Core project which contains resources shared by all the other projects and all. One of these is an image file, which I have had to copy to all the other projects to use a relative file path for the Source property of various ImageEdit controls.
How can I set things up so that the image file only exists in the Core project, and I can refer to it in XAML in all the other projects?

Reference the project from the project that you intend to consume the image, then use pack URI to access it.
Something like this:
<UserControl x:Class="MyProduct.MyModule.MyView"
.....
<Image Source="pack://application:,,,/MyProduct.Core;component/Images/MyImage.png"/>
Build action for images should be "Resource".

Add the image to your Core project, then add as linked item to your other projects (Right Click Project -> Add Existing Item -> Select the file from your Core project then instead of "Add" you need to click the triangle next to "Add" and say "Add As Link"). You can then reference it in the usual way from within your specific project...

Related

Resources from ResourceDictionary accessible but Styles are not

I'm hoping to create a WPF User Control Library with reusable controls for my many projects to save time recreating them every time (something I've found myself doing).
So I:
Created a WPF User Control Library, and created a ThemeDark.xaml file to contain common colour keys and styles.
Created a separate regular WPF project in the same solution so that I can test the controls in an actual window.
Added a project reference to the User Control Library.
Added a ResourceDictionary.MergedDictionaries into the App.xaml which references the theme file from the other project.
The problem: I can access and use the SolidColorBrush keys from the theme file just fine in the testing project, but for some reason IntelliSense can't see the Styles (which all have keys).
I also can't seem to use the pack://application:,,,/ method of referencing the ResourceDictionary in App.xaml; it only accepts the filename. This was originally set through the Properties panel -> Source -> Browse, however I have tried a few different formats, all to no avail. It also doesn't seem to notice that ThemeDark.xaml is in a Themes/ directory within the User Control Library project.
So - How does one properly reference a ResourceDictionary from a WPF User Control Library project and be able to use all resources (including Styles)?
DarkTheme.xaml (inside user control library project):
App.xaml (inside testing project):
Resulting behaviour (very strange - SolidColorBrushes available but Styles aren't):
I found the problem. I had removed the spaces from the project's namespace, but not from the assembly name.
Once that was fixed I was able to use Source="pack://application:,,,/MyControlLibrary;component/Themes/ThemeDark.xaml"
MyControlLibrary isn't the actual name! ;)

VS2012 - Add WPF existing user control to project

This seems like it should be pretty simple but I can't seem to make it happen. Lets say I have an existing project with a user control named uc1. I would like to use this user control in another project. I right-click the project name in the solution explorer and select add>existing item, change the drop down to all files and select the files uc1.xaml and uc1.xaml.vb. This of course adds the files to the project but there is no correlation between the xaml and the code behind file and there is no way to use the control. What is the proper way of doing this?
Reed's answer is a good architectural one. If you plan on creating a control that you will reuse in many projects then it's best to use a control library.
Your original question is valid in some situations though. Say you have some source code from the Internet that you've unzipped to your drive. This project contains a .XAML file and its linked .vb file that you want to add to a project.
As you seen, the Visual Studio Solution Explorer doesn't link the files when adding with the "Add Item" dialog. I think this is a bug. I find that if I reload the project, the affiliation is added.
Here's a workaround I use. I drag the files from Windows Explorer /File Explorer onto the project in Solution Explorer. That works correctly the first time.
This of course adds the files to the project but there is no correlation between the xaml and the code behind file and there is no way to use the control. What is the proper way of doing this?
Normally, you'd add a reference to the other project, and use the UserControl directly.
This allows you to build a single project with your UserControl, and use the resulting assembly (DLL) in multiple projects without duplicating the code.
If you want to reuse your user controls you need to create a new project and choose "Class Library" from the list of available projects. When compiled this class library can easily be used by any number of other projects and solutions simply by adding a reference to compiled DLL created when you build this class library.
Edit: As mentioned in other answer it's "WPF UserControl Library", not simple "Class Library"...
You just need to add the .xaml file and VS should auto add the code behind(nested). I've seen this not work a few times and as #Walt Ritscher said this is probably a bug.
I found simply restarting Visual Studio and reloading my solution worked.

Can't find ResourceDictionary in Add New Item Window

When I create a new WPF project I can find ResourceDictionary in Add New Item Window.
But I've another Project I can't find that and I don't know why.
UPDATE:
The project was for .net 3.5 originally, but now it also has a version for .net 4.0. It means there're two .sln files (one for 3.5 and the other for 4.0) both for the same project.
Add the following line to Project.csproj
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
It should be a child of the <PropertyGroup> tag, like so:
<Project>
<PropertyGroup>
....
<ProjectTypeGuids>{guids};{go};{here}</ProjectTypeGuids>
...
</PropertyGroup>
...
</Project>
This post does a good job of explaining why this works.
First of all, I hope you realize this shouldn't stop you since you can easily add any file you want to a project, either from your file system or by copying it from another project. The Add New Item window is just for convenience.
Secondly, when you added the new project to your solution, which project template did you choose? The project template determines the initial set of referenced assemblies that project has. A WPF project makes references to the WPF libraries (WindowsBase, PresentationCore, etc.).
Visual Studio uses your referenced assemblies to generate the possible items you see in the Add New Items dialog.
So I'm assuming you added some other type of project, such as a basic Class Library. You could manually add the references to the WPF assemblies using the Add Reference dialog. Or you could re-create the project as a WPF Custom Control Library.
Close the project. Create a new project that is of the type of WPF project you would have used(or use existing one). Then open the .csproj file of WPF project in text editor. Find the ProjectTypeGuids element.
Open your existing .csproj file in notepad. See if it has ProjectTypeGuids element. If it does, append GUID(without the ProjectTypeGuids) from WPF project in your existing project. If your existing .csproj file doesn't have ProjectTypeGuids element in it, copy ProjectTypeGuids from your WPF project together with GUID and paste it in your existing project in the first PropertyGroup element.
Reload your project in Visual Studio. You should be able to add all the WPF file types now.
I believe the GUIDS are the same for everyone so the values you need should be: {60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC} ... this should save you the step of creating a new project.
So if you have a class library project, just add
<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>
To the first PropertyGroup element in your .csproj file.

wpf Image resources and visual studio 2010 resource editor

My motivation for this question is really just to specify an image to be used in a user control via a dependency property for ImageSource. I'm hitting some pain points involving the management, access, and unit testing for this.
Is the resource editor a good tool to use to maintain images for the application?
What is the best way to translate the Bitmap from the editor to an ImageSource?
How can I grab the resource Filename from the editor?
No, the resource editor is not a good tool for this.
In a WPF application the best way is to put all of your images in an "Images" directory and mark each one as a "Resource". Then you can reference them directly in Image controls and elsewhere.
Here are the precise steps:
Crop and otherwise adjust your images using your favorite bitmap editing program (Paint.NET, Photoshop, etc)
Save them as .png files (or .jpg or .gif if you prefer)
Create an "Images" folder inside your Visual Studio solution (or multiple folders, however you want to organize it)
Drag the images from your hard disk into your "Images" folder (or right-click the project, select New -> Existing Item and select the images)
Now you can reference your images easily in XAML:
<Image Source="Images/MyImage.png" />
Or in code:
var source = (BitmapSource)Application.LoadComponent(
new Uri("Images/MyImage.png", UriKind.Relative));
You can also reference images in external assemblies:
<Image Source="ReferencedAssembly;v1.0.0.1;component/Images/MyImage.png" />
Which in code would be:
var source = (BitmapSource)Application.LoadComponent(
new Uri("ReferencedAssembly;v1.0.0.1;component/Images/MyImage.png",
UriKind.Relative));

Why does the Image element give me a design-time error with "add as link"ed images?

I need to display an image, which I've done without problems before, but today I decided to be tricky and use "add as link" instead. Well, now I get:
The file Images/hello.png is not part of the project or its 'Build Action' property is not set to 'Resource'.
Wait... its Build Action is set to Resource. I've seen a Silverlight solution that involves the usage of Merged Dictionaries to share files between Silverlight and WPF projects, but it's not clear to me that this would even apply to my WPF + Image issue.
Has anyone solved this problem before? I could make copies of all of the images, but that seems a little silly if I have a shared repository with clip art and the like.
Dave,
I've just tried to add image as a link to plain WPF application. Build action is "Resource" (don't confuse with "Embedded Resource"). I've added it to the root, and refer to it as <Image Source="/file_name.jpg"/> - all works fine.
The message you have is it compile or runtime? If it's a runtime, how do you refer to the image? Do you see it in Reflector, when you open your assembly (it should be under Resources folder)?
I have images in one assembly which I want to share into another. I've used Add as Link in my second assembly. In the project where the actual image files are located they are in a Resources\Images folder. In the project which links to those files the links are also in a Resources\Images folder. At runtime a XamlParseException claiming "cannot locate resource" is thrown.
My xaml which is referencing the image is in a UserControls folder.
In the project which actually contains the images the path ..\Resources\Images\Blah.png works fine as expected.
Opening the DLLs in Reflector makes it obvious that in the assembly with the linked images holds the images at the root level - the compiler is not respecting the folder location. So in the project with the linked files I have to use ..\Blah.png to find the resource.
Surely a bug in the compiler?

Resources