Arnaud F.
Arnaud F.

Reputation: 8452

C# - Separate UI from business code

I want to know what's the best practice for the following case :

I'm developing an application that need to be used on three different screen size : 240x320 ; 800x600 ; 1280x1024 (and only these three) in different languages (using localization).

So what I've done is to create a library by screen size, each implementing an interface defined in the project that calls these screens.

First question is, all my resources files are duplicated and that is many files to keep up to date (or with duplicate labels). Is there a simple way to change this?

Second question is, am I using the good approach or exists it a better way to do what I'm trying to do? By applying a design pattern maybe?


Sample code

The caller code :

    public int X { get { return 800; } }
    public int Y { get { return 600; } }

    public interface IScreenForm
    {
        Form FormComponent { get; }
    }

    public interface IFormA : IScreenForm
    {
        TextBox UserTextBox { get; } // For use
    }

    public void LoadForm<T>()
        where T:IScreenForm
    {
        if (!typeof(T).IsInterface)
        {
            throw new ArgumentException(typeof(T).Name + " is not an interface");
        }

        Assembly screenAssembly;
        string screenResolutionDll = string.Format("{0}_{1}_screens.dll", this.X, this.Y);

        screenAssembly = Assembly.LoadFrom(screenResolutionDll);

        Type formType = screenAssembly.GetTypes()
            .FirstOrDefault(t => t.GetInterfaces().Where(i => i.Name == typeof(T).Name).Count() > 0);

        if (formType != null)
        {
            Form form = (Form)formType.GetConstructor(new Type[] { }).Invoke(null);
            if (form != null)
            {
                form.Show();
            }
            else 
            {
                throw new ArgumentException("Form doesn't provide a new() ctor");
            }
        }
        else
        {
            throw new ArgumentException("Any form doesn't implement the interface : " + typeof(T).Name);
        }
    }

Screen DLL :

public partial class MyFirstForm : Form, caller.IFormA
{
    public Form1()
    {
        InitializeComponent();
    }

    /* caller.IFormA interface implementation */
}

Upvotes: 4

Views: 981

Answers (2)

rene
rene

Reputation: 42483

It is hard to advice without getting the whole picture but for some tips that might by handy read this

http://msdn.microsoft.com/en-us/library/ff648753.aspx

about the SmartClient software Factory.

It comes with architecural guidance and solutions for issue you often see in this kind of apps

Upvotes: 1

Radim Cernej
Radim Cernej

Reputation: 794

Arnaud, from my own experience, from reading, and from talking to experienced developers: When it comes to supporting multiple screen sizes and with localization, there are no magic bullets. For localization put all your strings in resource files, or even in data files.

As far as the screen sizes, I would not try to be too clever. Yes, make sure that none of your business / non-GUI logic gets duplicated, but duplicating resource files, forms, etc - I would not worry about it. Some GUI frameworks like Qt and GTK auto-resize and auto-position GUI-widgets (e.g. Qt has 'spacer' widgets). It works OK most of the time, however I still prefer explicit control. With GUI programming, there are often unexpected glitches, having three independent sets of GUI components will allow you to address them, should they arise. Some example sources of problems: 1) Font sizing. 2) Windows accessibility settings. 3) Some national languages have longer average words than others, the long words have trouble fitting in the real estate available.

If I were in your shoes, I would look for example how browsers handle this (e.g. mobile vs. desktop version) and I would try to find some practical advice on the Web (like here at SO). I doubt that books on design patterns will help much with this. Disclaimer: I am a design-pattern skeptic.

Upvotes: 3

Related Questions