This project is read-only.

Correct way to subclass/override framework

Mar 12, 2013 at 8:02 PM
Hi all,
I am new to WPF and the CODE fw and am working on a number of somewhat related applications, all of which I want to base on the CODE fw.

In some cases, I need to create and/or override behaviours in the framework.
  • I could modify the fw - but this is not good, especially if I want to implement a future revision.
  • I could add the code to each project - but then I have duplicate code.
So I want to create some sort of middle layer where I can put the code. In the case of pure OOP coding, I could just create a project that contains subclasses of the code in question and then put my enhancements there. And for some parts of the CODE fw, I could still do this. But I am totally lost when it comes to what to do with the XAML stuff.

Do the fine folk at EPS/CODE Magazine have an established process to implement this middle layer? I would think so because I am under the impression that they have a number of extensions to the fw that they use inhouse and those would need to be implemented this way.

Any thoughts/comments/references to link/etc. on the best approach to do this would be appreciated.

And it may be that I will find the info as I wade through all the discussions, documents, and previous issues of CODE Magazine - but I am guessing that someone already knows the answer.

Thanks
Mar 16, 2013 at 4:51 PM
Yes, this is certainly possible. Generally speaking, in WPF (so this is not CODE Framework specific), one probably needs this a little less in prior MS/.NET techs, but it is possible in very similar ways.

For code, you can use techniques like subclassing and composition. You can create yourself a new project and put everything you need in there and then include the resulting DLL(s) in your other projects. Nothing really unusual about it being WPF (or CODE Framework for that matter) here.

XAML is a little different, and techniques like subclassing do not really work there. You can to replace complete resources at once. The only aspect where you can kind of use a subclassing like technique is with styles that can be based on other styles, so you can certainly use that. We also try to break resources into as many small pieces as possible, so if you then want to augment or replace one of them, it's as feasible as possible. This is something I would recommend in general in WPF/WinRT/XAML.

Anyway: Once you have XAML in a new project, XAML can be compiled into DLLs like anything else in .NET and then be used from there. That is what we do with the default themes for instance. It's a big question to answer though, as there are many different scenarios, so to give a more specific answer, I'd probably have to know what the exact scenario is you are trying to address.


Markus
Mar 18, 2013 at 6:28 PM
Edited Mar 18, 2013 at 7:05 PM
Markus,

Thanks. So I can create a project that essentially builds the same dlls as are build in the CF, all based on the dlls from the CF. Then I use those for the external components when I create a new project. No problem with the .cs code.

With the xaml, the FW apparently uses the ThemeRoot.xaml to load all the resource dictionaries. Then it looks to the Metro.xaml (or whatever theme is selected) to load any additional resource dictionaries.

In my intermediary framework (IF), I specify a theme (say Metro.xaml), then in that, I would need to add a reference to an application specific resource dictionary (Maybe MetroApp) that could then, in turn be used to override any of the themes overridden/added in the IF (or even the FW).

Given the following:
ThemeRoot.xaml (in the CF project):
<ResourceDictionary Source="Metro-Control-Button.xaml"/>
<ResourceDictionary Source="Metro-Control-CheckBox.xaml"/>
....

Metro.xaml (in the IF project):
<ResourceDictionary Source="Metro-Control-Button.xaml"/> <!-- This being local to the IF project and overriding the default one -->
<ResourceDictionary Source="Metro-Control-Special-Button.xaml"/> <!-- This being local to the IF project and being added-->
<ResourceDictionary Source="MetroApp.xaml"/> <!-- This pointing to an empty xaml file which can be overridden in an application project and needs to be last -->

MetroApp.xaml (in the application project):
<ResourceDictionary Source="Metro-Control-Button.xaml"/>  <!-- This being local to the App project and overriding the one in the IF -->
<ResourceDictionary Source="Metro-Control-Special-Button.xaml"/>  <!-- This being local to the App project and overriding the one in the IF -->
<ResourceDictionary Source="Metro-Control-CheckBox.xaml"/>     <!-- This being local to the App project and overriding the one in the FW -->
I assume that even if there are 2 .xaml files with the same name, both are loaded as they have different paths.
I also assume if a style with the same name is in 2 different resource dictionaries (with the same or different names), the last one loaded is used when the code is run. Is this correct?

If I only wanted to change one setter property/value in a given style (say I wanted change the BorderThickness from 2 to 3 in the RichTextBox control), would I have to make a copy of the entire style and change that one setting or is there a way (in a xaml file in the IF or application project) that I can override just that one setting? I know I can do it with code, but then I would have UI values in code, which we are trying to avoid.)

Or am I just over complicating things?

Thanks
Mar 18, 2013 at 7:18 PM
Marcus,

In spending some time with this, it is appearing to be much more complicated than I had hoped. There are many references to the CODE.Framework.xxx namespaces scattered everywhere. And there are a number of other areas where this is appearing to be problematic.

But I understand that EPS uses the CODE FW for their apps, but have a number of extensions/enhancements that they have added. I have to assume that many of these are used in multiple applications. Does EPS simply copy over those extensions into each project or do they have some way of sharing (at least some of) those common extensions between projects? Or should I look for hooks, extension methods, and other types of approaches to enhance the CODE FW without having to actually try create an intermediary layer?

Thanks
Mar 18, 2013 at 7:31 PM
Edited Mar 18, 2013 at 7:31 PM
Here's the general rule for WPF: You can have any name for XAML files, even the same name (if you can create the file, you are good basically). Resources that are loaded later override resources that are loaded earlier. So if your same XAML files have the same resources defined, then last one wins. It is perfectly fine to do that and in fact a handy technique to override existing resources. This applies to all XAML dialects, btw, not just WPF. And this is not CODE Framework specific.

For specifics on how CODE Framework loads certain resources, check out this article: http://www.codemag.com/Article/1211091

As far as overriding individual settings goes: Styles define values for properties. Things like colors or fonts and such. Example:
<Style TargetType="Label" x:Key="bla">
    <Setter Property="Background" Value="Green" />
    <Setter Property="FontFamily" Value="Comic Sans MS" />
</Style>
You can then create another style based on this style, which is very similar to subclassing:
<Style TargetType="Label" x:Key="something" BasedOn="{StaticResource bla}">
    <Setter Property="Background" Value="Red" />
<Style>
This way, you can override individual settings but the other ones (font in this case) is preserved. This works for all properties. Note however that some properties themselves are extremely complex. The templates are a perfect example. So if you want to override the template, it's either re-defining the whole property/template or nothing. And that is typically where copy & paste comes in. These templates however can use other resources which you may be able to break out separately and then you can override just those. We usually go out of our way to do that, so one has more fain-grained control.

I am not sure what you mean about the namespaces. Yes, there are quite a number of DLLs. They are deliberately broken out so people can choose what to deploy and thus get as little overhead as possible. You will only need a sub-set. For instance, WPF projects only need the CODE.Framework.Wpf.xxx DLLs and not necessarily even all of them. You should only have a need to subclass very few of them, if at all. And of course you can put all your extensions and subclasses into a single DLL if you want.


Markus