I want to develop a robust system written in C# (WPF and WCF) for importing .csv files (and/or some others e.g. Word files) as a input into my system and then to generate PDF/Word report.

I would have database, and application will be a desktop app.

I am just wondering is there any approach for multiple customers apart from creating as many forms as customers? (1 form - 1 customer, 5 customer - 5 forms) depending on specific request of each of them?

Picture is below.

enter image description here

  • Gotta agree with gnat on this one. Learn how to choose the right pattern, and you'll have the right pattern. – Robert Harvey Aug 28 '17 at 15:01
  • Of course, but I thought that someone had similar experience. Tnx anyway. – Stefan0309 Aug 28 '17 at 15:42
  • I agree with Robert and gnat that this is currently not a good question for this site, however not for the reason you were told. Even when you remove the word "pattern" from the question and replace it by "approach", it is still quite unclear. A WPF desktop application installed on each client will open at least one form on the users machine, but that is trivial and nothing which requires any "design decision" of yours, so I have actually no idea what you are talking of. – Doc Brown Aug 28 '17 at 19:00
  • @DocBrown Sorry for misunderstanding. It is one desktop app, but GUI depends on client. For example, I work every day in that new program, with one client. That client has some options/features. Tomorrow, I get another client but nature of his business is little different, and I need to add some check mark or something for that client. My question is how to avoid multiple forms for different clients? I think is clearer now? Thanks. – Stefan0309 Aug 29 '17 at 7:04
  • It is clearer now. I edited your question and replaced the word "client" by "customer", because "client" is ambigous in the context of client-server systems. – Doc Brown Aug 29 '17 at 8:58

Note: The question specifically mentions WPF and XAML, so this is a WPF and XAML-specific answer based on a WPF app I've worked on, with similar requirements to customise isolated parts of the UI. The general approach might apply to other UI frameworks with some extra work.

Firstly, creating a complete Front-end on a per-customer basis, while possibly undesirable, is not a completely invalid option, even if it results in a lot of copy+paste code with a lot of duplication in your UI layer. if this option is the easiest, simplest, and quickest way to get you to a deadline, then it might be your "best" option.

An option which reduces duplication is to create a modular front-end where you can customise individual components rather than complete pages, and design the app so that those components can be swapped in and out.

Microsoft's Prism Developer Guide

I strongly recommend you read Microsoft's Prism Developer Guide even if you are not going to use the Prism libraries.

(The name 'Prism' might be a little confusing because it's the name often used to describe the Libraries. The Guidelines are mostly applicable to any MVVM application with or without those libraries).

Microsoft's Patterns and Practices team recommend you create separate Views for each area of end-user functionality, and also suggest that you write your top-level layout separately those Views. i.e. Views which contain your generic or customer-specific controls and behaviour exist as entirely self-contained components.

(Chapter 7 explains this better than I could: https://msdn.microsoft.com/en-us/library/ff921098(v=pandp.40).aspx)

In short:

  • Views contain your actual UI functionality - controls, bindings, commands, triggers, templates. ViewModels, which should be tailored to individual views, contain the state of that UI. A View and ViewModel often has a one-to-one relationship.

  • Layout is typically your top-level Window which is purely structural and totally agnostic to any of the controls. Prism has a very useful concept called RegionManager which can do the hard work in connecting a View to the 'right' area of your Layout.

Creating a modular front-end will not necessarily eliminate duplication entirely, but should reduce it to a point where it's easily manageable and mostly irrelevant.

For example, consider a simple single-page WPF UI with the following functional elements:

  • Search Box + Button with filter options
  • Results list/table with headings
  • Editable item properties box
  • Statistics box

In a small, simple WPF app, you might end up with the following components by default:

FilteredSearchBoxControl / FilteredSearchBoxViewModel
ResultsTableControl / ResultsTableViewModel
EditablePropertiesControl / EditablePropertiesViewModel
StatisticsBoxControl / StatisticsBoxViewModel

MainWindowShell / MainWindowViewModel


Creating the "glue" to wire all this together can be nontrivial, so if you use the Prism library itself, you get access to the tools which make a lot of this easier to do, for example:

  • EventAggregator - Message-based communication between decoupled components and ViewModels.
  • Bootstrapper - base class for an IoC Container and some default registrations (such as the EventAggregator or RegionManager)
  • AutoWireViewModel allows XAML to hook into the IoC container for creating ViewModels without a default constructor (Avoids a messy Code-Behind).
  • RegionManager - manages view-switching in specific areas of the layout.

Some other suggestions:

  • Avoid putting your general-purpose logic into ViewModels, because replacing a View for a specific customer will probably mean writing a new ViewModel for that replacement View. (There's nothing wrong with creating very lightweight ViewModels under the MVVM pattern). Instead, put generic, non-customer-specific business or app logic in separate classes which are unconnected to the UI (application/business layer "stuff").

  • Create a customer-specific View for those areas of the app which need to change instead of changing the whole front end. For example, you might want a MyCustomerFilteredSearchBox with a new tickbox and an extra button - you can just add that View to the app without touching any existing UI code.

  • Create your own back-end application logic/configuration to connect specific customer controls to specific customers, and determine which configuration to use. Use the RegionManager to make sure that the right Views appear.

  • If you are writing a larger, more complex app, or need finer granularity than simply swapping Views at the top-level Shell, you can create Scoped Regions (essentially "nested" regions) - https://msdn.microsoft.com/en-gb/library/ff921162.aspx

  • Great! I will investigate Microsoft Prism definitely! Many thanks! – Stefan0309 Aug 29 '17 at 11:15

Lets say you have two different customers with similar, but not completely different requirements. Maybe you need to display individual company logos at the main form, maybe there is a checkmark for an extra option only required by one of them.

To reuse the same form for such a case, you need to make your application customizable. So when a user logs on to the system, the authentification process should provide your application with the information to which customer the user belongs to. So it can retrieve a customer-specific configuration (maybe fron the database, maybe hardcoded in your application), and change the user interface accordingly. For example, the customer-specific configuration might contain different file names for a companies logo in form of a picture file. The form initialization code can take this file name and display the correct picture at its top. Or, there is a boolean configuration option for displaying the new checkmark, then the form initialization can enable or disable that checkmark accordingly.

Of course, if the requirements become too different, at some point it makes more sense to create an individual form for a new customer, for example when there is a specific use case which is not part of the requirements of the other customers. This is a judgement call you have to make for the individual case.

  • Thanks. I had that idea in my head..I will pull from database which is client and therefore I will represent forms and data accordingly. – Stefan0309 Aug 29 '17 at 9:29

Not the answer you're looking for? Browse other questions tagged or ask your own question.