8

I develop a WPF application using MVVM and I am learning how to do things best.

I have a WPF form with selectors, two list with search fields, and some other elements. Currently all is in one form and it works. But by now the VM for that form has more than 800 lines and it is not yet finished.

I want to structure this form and the code better. I thought about regions, files with partial classes and user controls. I think user controls would be best because they encapsulate a couple of controls and logic. If I would use user controls then the amount of code in that window and VM would be drastically reduced.

To do this right I work through the book "Pro WPF 4.5 In C# 4th Edition", Chapter 18 - Custom Elements and the ColorPickerUserControl sample. The sample is about a color picker with three sliders and it has 150 lines of code.

I think I understand how it works but it seems to me that creating user controls, even with very limited functionality like in that sample, is a lot of work. If I would use these controls several times then I understand it would make sense to do this. But if I use the controls only one time and I do this only to structure my form then this seems to be a lot of work for little gain.

My question is: Is it good practice to use user controls to structure forms even if these user controls are only used once? If not, is there a better alternative?

Edit (not necessary to read, just more information): Until now I did not write any details because I wanted to learn about the principle but after reading 17 of 26’s interesting answer, here are some details: This form is to select music titles.

  • Group A: (possible user control A) is about the type of selection like select by artist or album, with or without video, maybe year of publication, etc.

  • Group B: This list contains artist names which are filtered according to criteria in A. The user can filter the list i.e. showing only artist names containing "top".

  • Group C: This list shows titles from the artist selected in B also using criteria from A (i.e. audio or video). It can be filtered similar to B i.e. only titles containing "you".

Most of the logic happens in the VM (DataContext of the form). The lists from A and B come from a database. The lists are filtered and prepared for presentation (i.e. multiple titles with the same name but in different albums). The user selects a title in the C-List by double clicking or uses drag and drop into another WPF form.

What I want: I want readable code so that I can easily amend it. If I want to add i.e. another filter let’s say to only show female artists then it would be good if I could just go to user control A and add checkboxes for male and/or female artists.

The XAML in the current form is no problem, it is well structured. But the VM has code for all of the above. Some things are in the constructor, some in the commands section, some properties and backing fields. I can still find things now but I think it would be better if the code would be more structured. This is why I think about the User Controls.

I try to follow MVVM because I think the logic behind it makes a lot of sense. But I am not a fanatic follower of any theoretical practice. I.e. if I can do something in 5 lines of CodeBehind or in 50 lines in the VM I will do it likely in the CodeBehind. My question is about the principle how to create structured forms in WPF. The form I describe above is a good example but the answer should not concentrate on this one single from but on the idea how to structure WPF forms i.e. with (or without) user controls.

About why I think user controls are a lot of work: They have dependency properties, routed events, etc. All this seems to me a lot more complicated than “normal” properties with backing fields and INotify. But maybe I just have to get used to dependency properties, routed events, etc.

  • I'm a bit puzzled as to why you think making user controls is a lot of work. In its simplest form, a UserControl is just a container. You make one like this: <UserControl> </UserControl>. That's it. – Robert Harvey Apr 13 '18 at 15:11
  • Regarding your edit: User Controls only have dependency properties, routed events, etc., if you decide to put those things in. They're not mandatory, by any means. – Robert Harvey Apr 13 '18 at 19:07
  • @RobertHarvey: Yes, I understand that. But it seems for "full functionality" with two-way binding, triggering something in the main form if something in the user-control was changed, etc. they are necessary. I think the sample in the book which I mention above shows how necessary they often (not always) are. – Edgar Apr 13 '18 at 23:16
  • Wouldn't you still have to do all that without using User Controls? – Robert Harvey Apr 13 '18 at 23:16
  • 1
    It also doesn't sound like the ViewModel is doing a heck of a lot. Sorting and filtering a list of results is a fairly small task for a ViewModel. Maybe the problem is not what the VM is doing, but how it is written. Perhaps there are some C# features you can use to reduce code size. Or maybe the VM can be refactored to shrink its size. – 17 of 26 Apr 15 '18 at 15:29
6

Absolutely yes. It is a good idea in the same way that it is a good idea to apply separation of concerns on classes to put each in its own in order to perform a single task. You may only have one instance of that class, but it matters not. The optimization is not in terms of program performance but in terms of organization and overall program "health".

You want to be able to return to your program one day and not have to scroll through several hundred pages of code, even if it is put into regions (using regions on classes with lots of code is like putting lipstick on a pig, by the way). Should you ever one day decide to use it somewhere else, you can do so gracefully and without many problems.

Just don't make the temptation of giving the user control access to the parent form. If you do it this way, use events to convey information to the parent, with the parent form as a subscriber.

  • Also, when you create a custom control, you can encapsulate the part of the presentation logic it's responsible for, which, if done right, will in turn make your presentation logic in the containing control simpler. – Filip Milovanović Apr 13 '18 at 10:56
  • "Absolutely yes" is a IMHO not a good answer when the effort for creating a user control is as high as the OP describes it. – Doc Brown Apr 13 '18 at 11:20
  • 1
    A VIewModel has a single concern of coordinating the user interface logic for a set of user interface controls. Breaking these up can be challenging and often doesn't make sense. – 17 of 26 Apr 13 '18 at 12:04
  • 2
    @DocBrown The question asks for opinions on practice in general. So I think Neil's answer is fair and an honest opinion. There is no absolute answer for anything, but we can always recommend somewhere to start. IMHO if I was being paid to code it I'd do it the right way (Neil's recommendation). Also - it could really help to do this if you ever want to re-use controls on future projects. But if I just want to play around or make myself something I'd just do it the quicker way because I'm already behind on my laundry. – Christopher Apr 13 '18 at 12:49
  • 1
    "absolutely yes" is incorrect. The right answer is "It depends". It adds cost and complexity to split up a View/VM into multiple Views/VMs. The benefit needs to outweigh the cost. – 17 of 26 Apr 13 '18 at 15:06
4

This is a really hard question to answer without seeing the actual code. You're also mixing terms a bit. User controls are not a 1:1 mapping with ViewModels.

User controls have a specific purpose in life: They are a composition of multiple UI elements that are used as a unit together. User controls are subsections of a View. This is very different from a ViewModel, which contains logic that a View is bound to.

Maybe it makes sense to break up your XAML into multiple user controls all driven by a single ViewModel. Maybe it makes sense to break up your XAML and C# code into multiple View-VM pairs. Maybe it makes sense to just leave it as you have it now. Impossible to tell without seeing the code in question.

What is your end goal here? Is the size of the code causing you actual pain or is this just to follow some theoretical practice?

Are you trying to reduce the size of your XAML Views or the size of your C# ViewModels? These are two very different tasks in the WPF MVVM world.

800 lines is not terribly big for a VM that backs a UI that has any sort of complexity to it. Breaking up a VM can often cause more problems than it solves. ViewModels make decisions like "disable this feature when this other list is empty". Trying to split up that sort of decision making across multiple components often does not make sense and will just add complexity to the code.

Now with that said, there may be work you're doing in the VM that has nothing to do with your ViewModel logic and can easily be partitioned into its own class. This would reduce the size of the ViewModel without increasing the overall complexity of the code.

I guess that was just a really long winded way of saying "It depends, and we can't tell without seeing the code in question".

  • Thanks for your answer. I never read about having multiple View-VM pairs - that sounds like an interesting idea. For the rest I added it to my question. – Edgar Apr 13 '18 at 16:18
0

If I, who know nothing about your app, had to add a new field over the surname field, or change the order of a few fields... I'd find it easy or daunting?

I dont trust on regions because the compiler won't checker whether you misplace something in the wrong region

You have to develop software with the aim of making easy for people to build upon what you created.

  • Did you ever create a form in WPF? If yes, then you should know that you would do what you describe in the XAML part of the form and not in the code behind or VM. Or to answer yours question: Yes, it would be very easy. – Edgar Apr 13 '18 at 15:15
  • @Edgar My fault. You talked about visual components and user controls and I thought that was all. If all your visuals are in the view, and all your business logic in the model, you should not worry of having a long VM. – A Bravo Dev Apr 13 '18 at 15:57

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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