How to remove baml from WPF assembly? - wpf

Using the merged resource dictionaries degrade application performance. In my assembly I often need to use merged resource dictionaries. I want to combine resources in one dictionary, and delete the original baml. I can't set Build Action to None (instead of Page), because in this case I lose some functionality (e.g., no syntax highlighting by resharper). How can I do this?

At run-time your application still need to read the linked BAML resources files, for this reason you can't remove BAML from your assembly.
For example:
You merge the following resource dictionaries
dictionary1.xaml
dictionary2.xaml
in merged.xaml.
You cannot simply remove the compiled XAML (BAML - dictionary1.baml and dictionary2.baml), because, as I wrote, at run-time you still need these resources.
But, anyway, you could literally copy the content of your XAML resources on merged.xaml, in this way you will have only merged.baml (after the compiler has generated it in your assembly resource part).

Related

Convert Baml file into usable XDocument for parsing

I want to be able to write unit tests against Xaml to look for improper patterns. We have issues where the Xaml is still valid and otherwise compiles and "works" fine but can cause hidden issues or lacks consistency. In order to help combat this we want to write unit tests against the files.
A simple example: If you define a grid and the grid column is bound to a numeric field on the underlying object then the column title of the grid should have the appropriate right align template per our internal standards. Leaving the template off the definition will yield a left aligned column header which doesn't really break anything other than our internal standards. Given this is basically xml, I should easily be able to write a test that interrogates the xml element, detects the existence of a numeric column and checks to make sure that the file also defines a title template that is right aligned. This way I don't have to rely on the developer or QA to cover things that are easily testable like this.
I have access to the assembly during the unit test process and can get to all the baml resource files by reading the manifest resource stream. But I can't figure out how to read them into a useful format that I could load into something like an XDocument for parsing and perusing. Has anyone done this? I've tried using Baml2006Reader, etc... without any good success.
If you want to convert BAML to XAML, you could take a look at the following BamlTranslator class on GitHub.
It uses a BinaryReader to decompile the BAML.

XMLNS : a way to set them once for all?

We have multiple namespaces and assemblies in my project, and so many xmlns to declare in each control we make (at least 7, without system ones like x: or d:). It's so tedious.
Is there a way to declare xmlns once for all in the application ?
If not, do you have some workarounds (in order to have a lightweight control definition) ?
Please note that I know XmlnsDefinitionAttribute, it's not always possible (with external ssemblies for example) or not a great design (for me it's not a great design to put an UI specific attribute in a business entity assembly).
xmlns are a document level thing needed by the compiler, they are like using statements which you will also have to place in every C# code file.
If you have many common xmlns you could create an item template for Visual Studio which adds them by default, or find an extension which allows for something like Snippets in XAML.

replace "DynamicResource" with "StaticResource"

To realize my application I have used a lot Blend3. When Blend3 wants to link a resource to another resource, it uses many times the link-type "DynamicResource". As I have understood (but I could have understood not well), the "Dynamic" links have sense only if I want to modify the links at runtime. In other cases they use more memory in vain. I don't want to modify anything at runtime, then the question is: have sense to replace "DynamicResource" with "StaticResource" in all my application?
Thank you!
Pileggi
Blend works better in design time with DynamicResource. See:
http://blogs.msdn.com/b/unnir/archive/2009/03/31/blend-wpf-and-resource-references.aspx
The money quote from that:
a) Should I use Static or Dynamic
resource lookup?
Blend def. plays
better with dynamic resource lookups.
You could use a static resource lookup
as long as the resource was not
located or merged into App.xaml.
People have raised concerns around
performance issues with dynamic
resource lookups (you pay for what you
get). While that might be true, an
interesting data point is that the
Expression Blend source code uses a
ton uses dynamic resource lookups for
our own UI (of course, we too use
static resource lookups in places
where the resource would never change,
or where it not possible to use a
dynamic resource extension, for
example non-DPs).

Adding XMLNS causes VS seize up

Currently in my XAML editor view I am experiencing frequent seizing episodes of around 3 seconds each. I've been able to narrow down the reason for it to custom namespaces.
By default, my page has the 2 default XMLNS declarations:
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
</Page>
This works fine, no seizing. However as soon as I add an XMLNS for controls inside my application it starts seizing up.
<Page
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:MyNamespace.Controls">
</Page>
Its not specific to just that namespace. I've tried a large variety of namespace combinations. Basically any XMLNS pointing to one of MY namespaces causes this issue.
I'm not really sure how to diagnose this issue. Any pointers?
SOLUTION
We found out the solution. We had a reference to a Microsoft assembly that was about 7mb in size (ACtiveX stuff for web browsers). When removed, everything sped up. We're now looking at ways to abstract that assembly so that it can exist in the runtime folder but no need for a reference to it from the project. Thanks all for your ideas.
First of all we should find out what happens when you close quote mark inside Visual Studio. It's just a program (although a good one) - debug it/profile it.
Do you have any additional plug-ins
installed? Turn them off.
Turn off Intellisense.
What happens with MS Expression Blend? Does it seize?
Turn off all antiviruses.
Run Process Monitor and track what happens with VS. Are there any errors with file name/registry keys resolution?
If nothing helped, use profiler on Visual Studio process.
If nothing helped, write your question on StackOverflow. Oh. Hold on. You did this already. Let's wait for more responses :)!
Cheers!
This could be that it is looking for something or that it is recompiling code.
Select the output tag to view compile activity, then see if that is what it is doing next time it siezes up.
In some projects we get this behaviour if we exit debug mode by pressing the stop debug button instead of exiting the program.
Also, there have been several bugs reported for Visual Studio hanging when using DataGrid controls with WPF, it could be related to this. Here are a couple:
http://wpf.codeplex.com/WorkItem/View.aspx?WorkItemId=10542
https://connect.microsoft.com/VisualStudio/feedback/ViewFeedback.aspx?FeedbackID=420621
Are you running a real-time virus scanner? These can often cause sluggish performance when VS needs to compile your code...
A plausible guess is that this behavior is tied to VS's XAML editor attempt to provide Intellisense for nodes declared with clr-namespace. This is after all one of the differences between clr-namespaces and other types of namespace (whereby the URI is merely taken as a unique string, but no attempt is done to assert the definition of the underlying XML language.)
A possible workaround is too define the xmlns prefix under a bogus URI, during the xaml editing phase (and hence forgo any hints from intellisense), and to revert to the proper clr-namespace for other phases of the project.
Also, maybe adding the assembly=xxxx to the namespace declaration may help the situation. Even if the assembly in question is that of the current application, this may save the editor and associated intellisense some hesitation.
Another, counter intuitive workaround could be to have these controls in a separate assembly, as this may spare the system from the Intellisense's attempts at dynamically inferring the types structure from the source code, with all the associated hickups caused for example by the background polling for changes etc. (I do not know that it tries to do that, but sometimes, tools are getting to be quite intelligent, but too result in CPU or I/O blocks of the kind you describe.

Loose xaml referencing versioned assemblies

I have a unique development situation and would like some input from others.
I have a situation where I need to load loose xaml files within a rich client application.
A given loose xaml file may have references to an assembly not currently loaded in memory
so the referenced assembly is loaded before the loading the loose xaml. The loose xaml and tied
assemblies are stored on different backend servers which are downloaded to the client and
loaded dynamically.
The loose xaml and/or assemblies are version specific and unfortunately the application can
not be shutdown between rendering xaml.v1 with assembly.v1 from server A
and xaml.v1 with assembly.v2 on server B.
Both assemblies use the same namespace declaration so "older" assemblies can still
work with "newer" ones for any given loose xaml.
The problem is, I do not get a reference to assembly.v2 if I load xaml.v2 which contains
references to "newer" features in assembly.v2.
I obviously cannot unload assembly.v1 from the app domain and I'm not sure if I can
reference items in xaml that are loaded within a different app domain through marshalling.
Any Ideas other than using different namespace references?
I'm guessing that you are already doing dynamic assembly resolution and loading? If so, then you could try substituting a fake assembly name in place of the real assembly name i n the Xaml - you can then use that in your assembly resolution code to load up and return the right assembly. e.g. if your original source Xaml is:
xmlns:myassembly="clr-namespace:MyApp.MyAssembly;assembly=MyAssembly"
and you know that Xaml wants v2 of MyAssembly, replace the assembly ref in the Xaml string before parsing it to:
xmlns:myassembly="clr-namespace:MyApp.MyAssembly;assembly=MyAssembly.v2"
.. then in your assembly resolution / load code, when you see the ".v2" bit on the end you look for and load that assembly instead.
Please let me know if I've misunderstood the question, or you aren't current doing any custom assembly resolution - that would certainly be the key in this situation I think.
Another option (assuming that you are versioning your assemblies properly) is to simply include the assembly version in the ns declaration, like so:
xmlns:ns0="clr-namespace:MyCompany.MyProject.MyNameSpace; Assembly=MyCompany.MyProject, Version=1.0.0.0"
I haven't confirmed if this would work, but I believe that it may. You could use the XmlnsDefinitionAttribute (at assembly level). E.g.
Assembly V1 -> AssemblyInfo.cs
[assembly: XmlnsDefinition( "http://schema.mycompany.com/myproject/v1", "MyCompany.MyProject" )]
Assembly V2 -> AssemblyInfo.cs
[assembly: XmlnsDefinition( "http://schema.mycompany.com/myproject/v2", "MyCompany.MyProject" )]
And then in xaml:
xmlns:myassembly="http://schema.mycompany.com/myproject/v2"

Resources