Including Unreferenced Assemblies Into ClickOnce Deployment

October 29, 2009 22:43 by Alec Bryte

Many modern modular application products consist of the main application and several plug-ins. it has become popular to utilize the Unity Framework and Prism for WPF, which allows decoupling of the parts of the application from one another. The plug-ins are loaded at runtime using reflection. Usually the main application has the list of plug-in modules to load defined in its configuration file. Naturally the main application does not need to know of the existence of a particular plug-in or its internal structure until the execution time.

In such Visual Studio solution it makes sense not to add the plug-in projects or assemblies as references to the main application. However this presents the challenge when one needs to deploy the application with the plug-ins via ClickOnce. The ClickOnce architecture doesn’t allow one to include arbitrary files that are not part of the project.

It turns out there is no real harm in adding a project reference or a DLL reference to the main project. It’s true that during the compile time, the referenced assembly is passed to the compiler as the /r:MyReferencedAssembly.dll. However the compiler is smart enough to recognize that the main project makes no use of any of the classes inside the child assembly, and the reference is simply ignored.

For example, in the following screenshots, I used Red Gate’s .NET reflector to show that even though I added a reference to the project called MyPlugIn, the compiled assembly does not have any reference to it.

image

image

I hope this article saves time for another perfectionist developer like me :)


WPF Proportional Panel

January 16, 2009 12:59 by Alec Bryte

Standard Layout

Windows Presentation Framework provides a great flexibility when it comes to the layout. There are several Panel controls a developer may use to position elements, and they include:

  • Canvas - for absolute positioning of elements using (X,Y) coordinates. Useful for drawing custom graphics
  • Grid - most commonly used layout control. Allows dividing area into rows and cells and automatic alignment of controls placed inside the cells.
  • StackPanel - ideal for placing several controls next to each other, horizontally or vertically
  • DockPanel - aligns elements to a particular edge and allows an element to stretch and fill the remainder of the space

Custom Layout

All WPF panels are derived from Panel public class, which means one can create his own custom panel implementation.

In my case, I needed to create a special type of a panel that would resize the child elements based on a given percentage value. For example, assume two elements are in the panel positioned horizontally and the first one has a value of 20%, while the second one is 80%. The width of the first element would be 20% of the total available width, and the remainder would be the 80% of the width taken by the second element.

Here is an example with 4 elements:

ProportionalPanelDemo

Notice how the elements have their widths proportional to their percentage values.

To achieve this behavior we will create a class ProportionalPanel derived from the original Panel class. There we need to override 2 important methods that take care of the layout logic: ArrangeOverride() and MeasureOverride(). Basically, when a panel renders elements, it first asks each child for its current size. It then uses the values to properly position the elements.

        protected override Size MeasureOverride(Size constraint)
        {
            [...]

            double totalProportion = 0.0;
            foreach (UIElement child in this.Children)
            {
                 totalProportion+= GetProportion(child);
            }
            foreach (UIElement child in this.Children)
            {
                if (Orientation == Orientation.Horizontal)
                {
                    childWidth = constraint.Width * (GetProportion(child) / totalProportion);
                    childHeight = constraint.Height;
                }
    [...]

Note that GetProportion() is implemented as an attached property. This allows setting Proportion values on elements inside our panel. Since we want to allow just about any element (TextBox, Grid, ComboBox, Rectangle) to be placed inside the panel, even a custom element, such elements won't have a Proportion property by default. Attached Properties is a new and a very powerful feature in WPF that allows extending of existing classes with custom properties.

Using Proportion attached property, we can set the value as follows:

<ctl:ProportionalPanel Orientation="Horizontal" >
    <TextBlock Text="Apples" ctl:ProportionalPanel.Proportion=".20" />
    <TextBlock Text="Oranges" ctl:ProportionalPanel.Proportion=".15" />
    [....]
</ctl:ProportionalPanel>

Complete Solution

Click below to download a working Visual Studio 2008 solution of the WPF Proportional Panel.
ProportionalPanelDemo.zip (27.24 kb)