WPF exception adding new Resource Dictionary - wpf

I need to add some ResourceDictionary to a WPF window.
If I do as follow, everything works:
var uri = $#"..\..\..\Assets\Styles";
if (Directory.Exists(uri))
{
var allFile = Directory.GetFiles(uri);
if (allFile == null) return;
foreach (var file in allFile)
{
backupManagementWindow.MergeResourceDictionary(new Uri(file, UriKind.RelativeOrAbsolute));
}
}
Since that I don't want to define the Uri based on my executable directory, I define it as follow:
var uri = AppDomain.CurrentDomain.BaseDirectory + #"Assets\Styles";
The Uri is correct (there are the files) but then the code raise an exception.
public void MergeResourceDictionary(Uri uriResource)
{
var newResource = new ResourceDictionary {Source = uriResource};
Resources.MergedDictionaries.Add(newResource);
}
Does anyone know why? Thanks!

You can use Pack Uri Scheme when working with resource dictionaries.
And your uri would look something like this:
The following example shows the pack URI for a XAML resource file that is located in a subfolder of the referenced assembly's project folder.
pack://application:,,,/ReferencedAssembly;component/Subfolder/ResourceFile.xaml

Related

How to load WPF treeview resources from another assembly using MEF?

I'm creating a WPF application which loads its plugin using MEF.
How can I include resources from another assembly I'm loading using MEF?
Specifically I want to create an HierarchicalDataTemplate in external assembly and load it to a Treeview.Resources dynamically when composing the application on start.
Is something like this possible?
I'm using Caliburn.Micro if it matters but I'm sure the question applies to general WPF applications.
If you try to load static resources you should load the resource before loading the main window.
If you try to load dynamic resources you should load the resource before loading the view that uses the resource.
Any way you should add a reference to the resource by adding it to the Wpf Application merge dictionary while bootstrapping.
//On the bootstrapper add the following code
ResourceDictionary rd = new ResourceDictionary
{
Source =
new Uri(
"pack://application:,,,/DllName;component/Themes/ResourceName.xaml",
UriKind.RelativeOrAbsolute)
};
Application.Current.Resources.MergedDictionaries.Add(rd);
This is how I did it at the end.
Because Caliburn.Micro doesn't work properly if you use MEF's DirectoryCatalog to load your assemblies I had to do it manually. Bellow is the simplified part of the code that does it and loads the ResourceDictionary contained in the separate resources.xaml file.
FileInfo[] filesInfo = new DirectoryInfo(pluginPath).GetFiles("*.dll");
AssemblySource.Instance.AddRange(filesInfo.Select(fileInfo => Assembly.LoadFrom(fileInfo.FullName)));
// load resources from plugins
var dictionaries = App.Current.Resources.MergedDictionaries;
dictionaries.Clear();
foreach (FileInfo fileInfo in filesInfo)
{
string assemblyName = Path.GetFileNameWithoutExtension(fileInfo.Name);
string uriString = assemblyName + #";component/resources.xaml";
try
{
dictionaries.Add(new ResourceDictionary { Source = new Uri(uriString, UriKind.Relative) });
}
catch
{
// do some logging
}

Accessing the images folder in wpf app

I have a wpf application in which I want to save a file in the Images folder, which is on the same level with the bin folder.
How do I access that folder?
I try like this:
using (var imageFile = new FileStream((new Uri(#"pack://application:,,,/Images/Application/")).ToString(), FileMode.Create))
{
//
}
and I get the error that "The given path's format is not supported.". How can I access that folder?
Your path refers to resources within the project assembly. You should use relative or absolute file system paths:
var path = Path.Combine(
Path.DirectorySeparatorChar.ToString(),
AppDomain.CurrentDomain.BaseDirectory,
"Images"); // Result could be for example: "C:\MyWorkspace\MyProject\bin\Debug\Images"
using (var imageFile = new FileStream(path, FileMode.Create)) { }
How about using double dots(..) to get to parent directory.
using (var imageFile = new FileStream("..\..\[Path goes here]", FileMode.Create))
{
//
}

Winphone8.1 development: Can I get a List of al files stored within the Assets folder?

I am running win8.1 , and VS2013 SP3, trying to create a windows phone app which should retrieve all the document names and paths (for later reference) from the 'Assets' folder.
I added a bunch of word documents in the Assets folder and set the build to content, and copy to always.
Is it possible to get a list of all files (or file names) in the assets folder?
I can't seem to find the way to do it.
What I can do is reference a specific file, but what I would like to do, is list out all the file names/paths within the Assets folder and show the details of these files in a specific view...
I tried the following:
var package = Windows.ApplicationModel.Package.Current.InstalledLocation;
var assetsFolder = await package.GetFolderAsync("Assets");
foreach (var file in await assetsFolder.GetFilesAsync())
{
_documents.Add(new Document() { Category = section, Title = file.Name, Uri = file.Path });
}
This code freezes on the foreach line...?
I would very much appreciate some guidance or references in this matter.
Maybe it's the way you're calling it.
Here's mine with screenshots.
I only call it once the whole page has loaded.
private void Page_Loaded(object sender, RoutedEventArgs e)
{
ReadAssetFolder();
}
public async void ReadAssetFolder()
{
var package = Windows.ApplicationModel.Package.Current.InstalledLocation;
var assetsFolder = await package.GetFolderAsync("Assets");
foreach (var file in await assetsFolder.GetFilesAsync())
{
int debug_var = 1;
}
}
Screenshot of when the debugger hits my breakpoint:
Screenshot of my Asset folder
Finally all my files have these Properties
Hope that helps you.

How do I load an icon using GetResourceStream in WPF?

I've added an icon to my WPF project (BuildAction set to Resource) and I'm now trying to load that icon into a stream:
using(Stream iconStream = Application.GetResourceStream(new Uri("red.ico")).Stream)
{
// use the stream
}
This gives me the following error:
Invalid URI: The format of the URI could not be determined.
I've tried altering the Uri construction to include UriKind.Relative. This gives:
Cannot locate resource 'red.ico'.
I've looked at various articles on this For Example (from SO) and I can't see what I'm doing wrong.
Any help greatly appreciated.
Try something like new Uri("pack://application:,,,/red.ico"), see this page for more info on URIs in WPF.
Ultimately my issue boiled down to the fact that I had created a custom entry point for my WPF application and I was attempting to create a URI before the Application's static constructions had been called.
The code changed from something like this:
public static void Main()
{
var myUri = new Uri("/red.ico", UriKind.Relative);
var app = new AppMain();
app.Run();
}
to something like this:
public static void Main()
{
var app = new AppMain();
var myUri = new Uri("/red.ico", UriKind.Relative);
app.Run();
}

Relative Uri works for BitmapImage, but not for MediaPlayer?

This will be simple for you guys:
var uri = new Uri("pack://application:,,,/LiftExperiment;component/pics/outside/elevator.jpg");
imageBitmap = new BitmapImage();
imageBitmap.BeginInit();
imageBitmap.UriSource = uri;
imageBitmap.EndInit();
image.Source = imageBitmap;
=> Works perfectly on a .jpg with
Build Action: Content
Copy to Output Directory: Copy always
MediaPlayer mp = new MediaPlayer();
var uri = new Uri("pack://application:,,,/LiftExperiment;component/sounds/DialingTone.wav");
mp.Open(uri);
mp.Play();
=> Does not work on a .wav with the same build action and copy to output. I see the file in my /debug/ folder..
MediaPlayer mp = new MediaPlayer();
var uri = new Uri(#"E:\projects\LiftExp\_solution\LiftExperiment\bin\Debug\sounds\DialingTone.wav");
mp.Open(uri);
mp.Play();
=> Works perfectly..
So, how do I get the sound to work with a relative path? Why is it not working this way?
Let me know if you want more code or screenshots.
Thanks.
The pack://application URI syntax is for "embed" files, make sure the the media file is set to that, or use the pack://siteoforigin for "loose" files (copied to bin directory).
MSDN link

Resources