loading Markup::XamlReader::Load from resource file

J

John Dunn

Since currently we aren't allowed to have compiled XAML files embedded in C++
apps I'm using Markup::XamlReader::Load to dynamically load XAML files. This
works perfectly fine with external files but I'd like to be able to load a file
specified in a .resx resource.

I've added my .xaml file to the .resx and can load it in using
ResourceManager::GetObject(). The object returned is a System::Array^ which
contains System::Byte objects. The problem is that I can't figure out how to get
a stream from that which I can pass to XamlReader.

I've tried the following-

1. Use ResourceManager::GetStream(). This threw an InvalidOperationException
saying that the resource was not a stream, call GetObject instead.

2. Copy the Array to a IO::MemoryStream byte by byte. For some reason this
mangled the XML enough so that it couldn't be read. This also seems pretty
horribly inefficient.

Any help would be appreciated-

John
 
G

Gary Chang[MSFT]

Hi John,
This works perfectly fine with external files but I'd like to
be able to load a file specified in a .resx resource.

Based on my research, currently there seems not existed a direct way to use
Markup::XamlReader::Load from a XAML resource file. I suggest you can also
consult this issue in our corresponding MSDN forum, you may get more ideas
on this issue there:

Windows Presentation Foundation ("Avalon")
http://forums.microsoft.com/MSDN/ShowForum.aspx?ForumID=119&SiteID=1


Thanks!

Best regards,

Gary Chang
Microsoft Online Community Support
==================================================
Get notification to my posts through email? Please refer to
http://msdn.microsoft.com/subscriptions/managednewsgroups/default.aspx#notif
ications.

Note: The MSDN Managed Newsgroup support offering is for non-urgent issues
where an initial response from the community or a Microsoft Support
Engineer within 1 business day is acceptable. Please note that each follow
up response may take approximately 2 business days as the support
professional working with you may need further investigation to reach the
most efficient resolution. The offering is not appropriate for situations
that require urgent, real-time or phone-based interactions or complex
project analysis and dump analysis issues. Issues of this nature are best
handled working with a dedicated Microsoft Support Engineer by contacting
Microsoft Customer Support Services (CSS) at
http://msdn.microsoft.com/subscriptions/support/default.aspx.
==================================================
This posting is provided "AS IS" with no warranties, and confers no rights.
 
L

Laurent Bugnion

Hi,

John said:
Since currently we aren't allowed to have compiled XAML files embedded
in C++ apps I'm using Markup::XamlReader::Load to dynamically load XAML
files. This works perfectly fine with external files but I'd like to be
able to load a file specified in a .resx resource.

I've added my .xaml file to the .resx and can load it in using
ResourceManager::GetObject(). The object returned is a System::Array^
which contains System::Byte objects. The problem is that I can't figure
out how to get a stream from that which I can pass to XamlReader.

Are you using 2.0?

If so, try the following method:

Assembly oAssembly = Assembly.GetAssembly( tyResourceType );
Stream stmInput
= oAssembly.GetManifestResourceStream( strPathInResource );

Note that the path in resources starts with the assembly's name, and
uses '.' instead of the usual '\' or '/', so for example if your XAML
file is placed in a folder named "Xaml", the full path is (for example):

GalaSoftLb.MyApplication.Xaml.myxamlfile.xaml

Best way to find out what is the path of your resources is to
Assembly.GetManifestResourceNames in debug mode, and to check all the
resources' names.
http://msdn2.microsoft.com/en-us/library/system.reflection.assembly.getmanifestresourcenames.aspx

HTH,
Laurent
 
J

John Dunn

Laurent said:
Hi,



Are you using 2.0?

If so, try the following method:

Assembly oAssembly = Assembly.GetAssembly( tyResourceType );
Stream stmInput
= oAssembly.GetManifestResourceStream( strPathInResource );

Note that the path in resources starts with the assembly's name, and
uses '.' instead of the usual '\' or '/', so for example if your XAML
file is placed in a folder named "Xaml", the full path is (for example):

GalaSoftLb.MyApplication.Xaml.myxamlfile.xaml

Best way to find out what is the path of your resources is to
Assembly.GetManifestResourceNames in debug mode, and to check all the
resources' names.
http://msdn2.microsoft.com/en-us/library/system.reflection.assembly.getmanifestresourcenames.aspx


HTH,
Laurent

Thanks for the reply-

I'm using 3.0. I tried iterating the Resource names - only 1 resource was shown
even though I have 2 files added to my resx file. It returned
'db.test_resource.resources' where db is my app name and test_resources is my
resource file name. I'm not sure where it got the final resources string from. I
also tried iterating GetModules ( only returned db.exe ) and GetFiles ( returned
path_to_exe\db.exe ) without any luck.

The relevant portion of the resx file looks like this

<data name="window_close_button" type="System.Resources.ResXFileRef,
System.Windows.Forms">
<value>res\window_close_button.xaml;System.String, mscorlib,
Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>

The only other thing that may be an issue is that I'm calling
Assembly::GetExecutingAssembly() to get the Assembly. That seemed to work when I
needed an Assembly to pass into the ResourceManager constructor. If I need to
call GetAssembly I'm not sure what type to pass into that call.

Thanks-

John
 
L

Laurent Bugnion

Hi,

John said:
Thanks for the reply-

I'm using 3.0.

Oh, duh *LOL* Answering to a post in the WPF newsgroup, this should be
obvious to me. Sorry. I spend too much time in the ASP.NET and C# NGs ;-)
I tried iterating the Resource names - only 1 resource
was shown even though I have 2 files added to my resx file. It returned
'db.test_resource.resources' where db is my app name and test_resources
is my resource file name. I'm not sure where it got the final resources
string from. I also tried iterating GetModules ( only returned db.exe )
and GetFiles ( returned path_to_exe\db.exe ) without any luck.

I suspect that you add the files to the RESX file the old (1.1) way.

To add a file to resources in the 2.0 (and 3.0) way, you do as follow:

1) Add the XAML file to your project, using "Add existing file". The
file may be in a folder too, that's OK.

2) Select the file, select Properties (F4)

3) Set "Build action" to "Embedded resource"

Voilà. Next time you compile, the file will be added to the DLL without
you having to fiddle with the RESX file. Neat ;-)

After this, it should occur in the Resource names as standalone.
The relevant portion of the resx file looks like this

<data name="window_close_button" type="System.Resources.ResXFileRef,
System.Windows.Forms">
<value>res\window_close_button.xaml;System.String, mscorlib,
Version=2.0.0.0, Culture=neutral,
PublicKeyToken=b77a5c561934e089;Windows-1252</value>
</data>

Yes. Use the other way described above, it's easier and will act as
expected.
The only other thing that may be an issue is that I'm calling
Assembly::GetExecutingAssembly() to get the Assembly. That seemed to
work when I needed an Assembly to pass into the ResourceManager
constructor. If I need to call GetAssembly I'm not sure what type to
pass into that call.

GetExecutingAssembly() will return the current assembly, which is
probably fine for that you do. My code is generic, I use it in a Utility
class to extract resources embedded in any assembly, which I identify
using a type present in that assembly.

HTH,
Laurent
 
J

John Dunn

Laurent said:
1) Add the XAML file to your project, using "Add existing file". The
file may be in a folder too, that's OK.

2) Select the file, select Properties (F4)

3) Set "Build action" to "Embedded resource"

Step 2 isn't working for me. I add the resource with the 'Add existing file...'
button and the only properties I can set on my resource are (Name), Comment and
FileType. Filename, Persistance and Type are grayed out on any of the files I add.

I tried adding an image and I could then change the Perstance to either 'Link at
compile time' or 'Embedded in Resx'. Trying either of those didn't make the
image show up in GetManifestResourceNames.

I'm guessing that I'm missing an obvious step since this is my first foray into
Resource Assemblies.

John
 
L

Laurent Bugnion

Hi,

John said:
Step 2 isn't working for me. I add the resource with the 'Add existing
file...' button and the only properties I can set on my resource are
(Name), Comment and FileType. Filename, Persistance and Type are grayed
out on any of the files I add.

Strange. I just tried it again on a WPF application here, just to be
sure, and it works fine. I created a "Resources" folder, then added a
new ResourceDictionary (MyFile.xaml) in it, and then I can set the Build
action as I described. BTW, I use Visual Studio 2005 professional.

Can you tell me which type of project you created (WPF application?
XBAP? other?) and which version of the .NET Framework 3.0 you're using?
Oh, and also, which version of Visual Studio are you using?

Also, if you want, can you send me the project files zipped? (my email
address is genuine). Really curious why it doesn't work.
I tried adding an image and I could then change the Perstance to either
'Link at compile time' or 'Embedded in Resx'. Trying either of those
didn't make the image show up in GetManifestResourceNames.

I'm guessing that I'm missing an obvious step since this is my first
foray into Resource Assemblies.

John

HTH,
Laurent
 
J

John Dunn

Laurent said:
Can you tell me which type of project you created (WPF application?
XBAP? other?) and which version of the .NET Framework 3.0 you're using?
Oh, and also, which version of Visual Studio are you using?

I'm guessing the problem is that I'm writing a C++/CLI application. It doesn't
look like I have access to the same set of resource properties that C# apps
have. I'm using VS2005 so I'll send you a zipped project but I'm probably out of
luck.

I did a quick WPF project and I do get the Embedded Resource option.

John
 
L

Laurent Bugnion

Hi John,

John said:
I'm guessing the problem is that I'm writing a C++/CLI application. It
doesn't look like I have access to the same set of resource properties
that C# apps have. I'm using VS2005 so I'll send you a zipped project
but I'm probably out of luck.

I did a quick WPF project and I do get the Embedded Resource option.

John

I got your files. Yes, I guess that you cannot embed files in an
assembly the same way in C++ as you do in C#. I wasn't aware of the fact
(never tried managed C++, my experiences with C++ were in the embedded
world only, and a few years ago ;-)

I think that your idea to create a C# assembly for resources is a good
one. I hope that'll work better.

Greetings,
Laurent
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Top