Conditionally compiling UI components & logic - c#

I'm looking at producing a few versions of my app with restricted functionality, and I'd like to leave out the code that is not necessary in simpler versions. Being a WinForms app, the UI will have to change for each version - not displaying the restricted controls.
I made an attempt to annotate parts of the auto generated controls & layout code with conditional compilation statements, but I discovered VS throws out all my code as soon as I touch anything via the WinForms designer.
I would like to be able to conditionally compile some event handlers & UI controls. I could write the conditional UI code outside the designer file, but then I wouldn't be able to use the VS designer to edit my app.. Are there any suggestions to remedying this situation - i.e. conditionally compile UI controls & still have them display in the designer?
Thanks!

Not knowing how your UI forms look like perhaps you can create a base form that all versions share in functionality. Then subclass that with forms for the specific functionality. This way you can conditionally compile the sub forms rather than trying to turn on/off controls within the one form. However the subforms will typically extend the form downwards so weaving controls throughout the form might not work in this case.
Also if you use a presentation pattern (if you are not doing so already) such as MVC or MVP you can minimize the logic you have in the forms and push that to presenter/controller or even business classes that you can configure based on the version you are compiling against. These classes can get injected (DI) into the application based on some configuration.
Another option is not to compile out the form controls but hide them based on the version you are running but have the business classes compiled. This way the important 'intellectual' code is not in the app and you're not fighting with the winform designer.

Related

Design time events in WPF?

I am using Autofac with my WPF project.
At design time for some controls, I set the data context of these controls to a designer-specific view model. This view model then injects some services in through its constructor.
That's all fine. But how can I manage lifetime scoping for this? Is there any way to hook up to an event and dispose my Autofac container when the design-time phase is done?
You've said in comments:
The problem is that some of my services (for instance a hotkey service) is using the RegisterHotkey API. For that service, it's important that it is unregistered when Visual Studio is done rendering my design.
In general, those should not even get registered first when your component is in DesignTime. Designtime if for previewing the layout and inspecting view modes/states, not really for testing (though it's very tempting sometimes).
When in designtime, all interactivity of the component should be disabled. VisualStudio tries to do that, you will notice that many interactivity events/triggers are not invoked or passed to your component. However, it sometimes fails badly at this, like in case of Popups (and therefore Dropdowns, Comboboxes, etc) you can sometimes force to actually open in design-time and it yields very strange/unstable/otsafe results.
This is why you shouldn't fully trust VS and the design-time mode to "just work". You probably already know well that poorly written component can, in desing-mode, try for example to connect to a database. It shouldn't happen. Usually.
I'd say, refactor that hotkey-registering bits out into some service and stub/nullify/disable it when you detect designtime mode.
I doubt they worked in designtime, but if you needed these hotkeys to flip some switches in VM on and off, or to invoke some behavior, bind that switches or behavior to a few new properties, and instead of pressing hotkeys, set them in the designer or by designtimedata to check the effect.
Just FYI - I never researched this for WPF/XAML, but for WinForms, each component could come with a special "designer" component. VisualStudio used that 'designer' component for preparing, mantaining, rendering, editing and serializing the edited component. You could actually write a designer for your custom control, and that designer could display extra windows with custom editors, and so on. Toolkits like DevExpress heavily relied on that. I'm not sure if that there is a similar framework for XAML components. I doubt it's the same, but there may be some similar concepts kept. Anyways, I wouldn't dig into this on your place, not for such things. It's not worth it unless you really want to start extending the Designer with your custom plugins.

Dealing with control flexibility

I've a question more about 'Good Programming Practices'.
I have just started a really big project. I'm using WebGui (long story short.. it is WinForms in web) - but it's not important.
I'm creating milions of forms with milions of controls like TextBox, NumericUpDown, DateTimePicker and etc. It might happen, that I will have to change something in behavior of DateTimePicker or appearance. It will be impossible to change it in every control. I want my project to be flexible so I've got an idea..
I do separate custom controls for every type - string, numeric, date, byte.. and within I will put TextBox for example. And on every form I will put not TextBox, but MyTextBox. In fact, that MyTextBox will be just TextBox, but when I change something there, every control will be changed.
Is it good, popular pracitce in programming?
in the case of WPF this can be achieved quite easily using Styles and Templates.
in Winforms this is not possible, therefore I'd say your approach of deriving from the controls and using your own custom controls on the UI is a good practical approach which helps managing changes centrally.
If the controls were created manually in the programme, alternatively you could use a Factory clase(s) and get the Factories to create the controller object rather than just newing up.
But this might not be possible when the UI is created by dragging and dropping controls as the developer has no control over the creation of controls.
Which ever the approach you choose, the fundamental goal should be to centralize the creation logic of the controlls.
Yes, this is perfectly normal programming practice for GUI development, if the standard controls don't satisfy your requirements.
Most developers get 3rd party control suites for the extra flexibility. The benefits in buying far out weigh the benefits in building core controls yourself.
I've worked at a place that did companyTextBox, companyDatePicker and it worked ok. A couple of controls got revamped over .Net versions so these base classed controls required some surgery. Any depreciated controls were left as framework version dependent.
For special things, I do a lot of research into good custom controls on CodeProject, CodePlex, Code.Google.com,etc and implement them into the project I'm working on.
Otherwise use the stock standard controls or the suite of 3rd party controls the company I'm working for use.
My advice is to get a 3rd party suite of controls and make a ton of re-usable user controls based on the 3rd party ones. This way you can build most of the 200 forms by Drag and Dropping the user controls onto the forms. Make each User-Control Implement an Interface with Create,Retrieve,Update & Delete methods for the forms to generically work with your user controls.

Creating Custom Controls with .ascx files

I am looking creating some custom controls that need to be compiled as a stand alone dll rather than with the primary application. Unfortunately so far this has meant manually creating the controls without the use of the designer since afaik you can't compile a User Control as a stand alone component. As doing things this way makes the controls rather difficult for the designers to style without putting in a lot of effort on the developers part, I am wondering if there is in fact a viable way to compile a .ascx style control into a stand alone binary?
You can turn a user control into a custom control that is in a standalone .dll, but it loses the ability of being updateable via markup.
In other words, you can build an .ascx file using markup and code, and then turn it into something similar to a control that was built exclusively with code.
Turning an .ascx User Control into a Custom Control
You have to understand that user controls are just a convenience for reusable content though - ultimately, the markup does get processed and compiled. Custom controls are really the only way to distribute a web control. IF you have to distribute controls as a library, I would concentrate on making them CSS friendly for your devs with just a few layout controlling properties, rather than messing around with .ascx.
The MSDN article http://msdn.microsoft.com/en-us/library/aa479318.aspx explains how you can do this. Basicly you precompile the application and take the resulting DLL.

Modify Visual Studio's form designer code generator

I'd like to basically control the name of the method that the Visual Studio form designer uses for putting it's generated code in. By default, this is named InitializeComponent. But often times I need to have different layouts for different types of screen resolutions/aspect ratios (see Designing forms to work on different resolutions and aspect ratios on Windows CE for more detail). That way, at runtime I can choose how to layout the form by calling the appropriate one.
I realize that there is likely no trivial way to do this. I assume I'll need to build a custom VS add-in and extend the existing forms designer and hook into the code generator and layout interpreter for this to work properly. Any ideas on where I could start looking to make this happen?
Can you not switch within InitializeComponent and call different layout logic methods according to what platform you are?
if(platform.IsCE)
{
CELayout();
}
else if (platform.Tablet)
{
TabletLayout();
}

How could you enable a WPF application to create user controls on the fly?

How could you create an application that could search through a directory, find user controls in the form of paired .xaml / .xaml.cs files, and compile/execute these on the fly? Is this possible? Is there an .exec() or .compile() class somewhere that could do this?
Basically what I want to do with this is have a WPF application that is running and by having the user fill out a form describing the kind of page/functionality he wants, the application could generate XAML and code behind files which are then immediately usable without having to recompile the application.
I'm assuming that this is to change the behaviour of the UI on a known application rather than a XAML/CS component generator for use in another application - after all there's already applications that do this - Expression Blend anyone?
Do you really need to recompile the underlying CS? As far as I can see it all you'll be doing is changing the apparent behaviour and look of the application and UI. This could be achieved by command binding within the xaml and styles for the components.
The reality is that in order to perform the functionality that you require you'll be giving the user a finite choice as to behaviour. You'll need to decide what behaviour is application and what is the UI.
Application bahaviour is governed by fixed commands (they could accept parameters to change behaviour).
UI behaviour (appearance, animation etc) is covered by the xaml. If the application runs in a browser window you could auto generate the xml needed as requried, linking it to the underlying app. commands and allow the browser to execute the new behaviour for you.
Is this a good idea? I can see a few problems with this.
How will the code behind 'know' how to interact with the rest of the application
Security? You will be allowing somebody to make system API calls on behalf of the main application
App domains???
Rather build up the forms using ItemsControls and DataTemplates. In the form where the user specifies what functionality he wants in the form, you will be presenting him with a list of 'building blocks' anyway. Make each 'building block' a ViewModel and associate each ViewModel with a DataTemplate 'UserControl'.

Categories

Resources