Creating lots of user controls in WPF? - wpf

Is it normal in a WPF app to create a lot of user controls in order to separate concerns that would otherwise be crammed in a single window with a huge XAML hierarchy? I'm finding that I keep making new user controls, even though I don't intend to reuse them, just so that each of my sub-components has a separate task. I'm also giving each of them their own view model, instead of binding things to properties on one master view model.
Is this normal? I feel like from a code cleanliness perspective I'm doing the right thing. But from a WPF perspective, I feel that this can't be right.
For example, let's say you have a list on the left side of the window, and when you select an item, it changes what's displayed on the right side. There are also buttons above your list to manipulate it, adding and deleting items for example. I would be inclined to pull that whole list out as a UserControl, which would contain just the list and the control buttons above it. Then the main window would just include my new control.
Am I going overboard?

Related

When to use custom user controls

I've got a massive UI that I'm designing. The way that my employer wants it, there are at least 100 labels. Now, I've always thought that in cases like this, breaking up the UI into smaller custom controls was the ideal way to go. However, someone recently told me that custom controls are really only for code re-use. What is the actual suggested practice for this?
EDIT
The finished form will look like this:
Now, I'm using WPF for the UI, and I'm thinking of breaking this down into smaller bits.
Based on your image i see some repetitions, each of this repetitions could be a custom UserControl
But it depends on the usability is it easier to write a custom UserControl so do it but if it would reduce the readability of your code and it also adds additional complexity don't do it
here are an example of what could be separate UserControl's
the green ones are possible useful encapsulations of logic
the orange ones maybe need some not market stuff (don't know enough about your software)
the red ones are the maybe's based on the intern use (from the visual part they are repetitions so the should custom UserControl)
Since your UI is read-only, I'd suggest using a grid.
Are you new to WPF? To break the View into bits WPF offers you CustomControls and UserControls. They are two very similar things yet completely different from each other. CustomControls are Buttons, Labels, TextBoxes, DataGrids...etc. They are basically simple stand-alone controls. UserControls are groups of stand-alone controls serving a purpose such as example a Button and a ComboBox next to each other so user can select something in ComboBox and confirm that by clicking the Button.
If you wish to display data from database I suggest you DataGrid which will give you a table-alike look with rows and columns and all that. If you wish to place few buttons next to DataGrid on which the user may click to insert a new row or to edit a certain cell then I suggest you to wrap all that with a UserControl which you can reuse in other places where you have to display and change data from database too.
You should be using a datagrid and can customize its template to render individual cells as Textblock (lighter version of Label) from a rendering perspective. The main difference between Textblock and Label is very minor things such as access keys and disabled state behavior. But from a WPF object hierarchy - Textblocks are much lighter. But besides that point - from your employer perspective - once you have customized the grid template and render them (so as they look as textblocks/labels) - your employer should have no problems.
Also as somebody suggested above - if you want to logically break sections of the UI since they maybe coming from a different table in db - then User controls is the way to go (for maintainability of code)
Let me know if you are looking for more technical details or need help further technically.
There is nothing wrong in making and using custom controls or user controls or defining some data templates which will be reused depending on how your data is organized.
For sure the UI looks pretty messy and some sort of grid should be used with templates for example where there is similar data. I also have the suggestion and first think about the data and the functionality before starting and let the UI be driven by that. For sure you will the reuse controls/templates. If you think in front on the model and behavior the UI can afterwards more easily changed.
Create your viewmodel correctly, implement the functionality in commands, use bindings, after that the UI will come naturally, reuse controls, use several grids, make the UI more user friendly using several regions, tabs, windows or anything that makes the user more comfortable.

WPF Printing multiple pages from a single View Model

I am currently a little bit troubled by the following problem. I have a user interface which basically shows a graphic (a canvas made of Lines, Circles, ... these are all WPF objects). Depending on the selection a user makes in the menu, some items get deleted and some get added. So the basic image looks the same, but a few modifications are made.
The user has the possibility to select - say - 10 different "pages" by clicking a Next/Previous Button.
I am using MVVM Light and my ViewModel contains all the items of the graphic (all Lines, ...).
Now I would like to print that graphic to multiple pages. The first page should contain the graphic with changes from page 1, the second page contains the graphic with changes from page 2 and so on. The actual number of pages is dynamic. I track this with a property CurrentPage and a property PagesTotal.
Whenever I push the "Next" button, this causes a command to be executed which will change the variable CurrentPage and also makes sure that the correct items are displayed.
Now I would like to print this but this is where I'm stuck. I dont' mind leaving the MVVM zone and doing some dirty work in code-behind but I would refuse to draw everything again like in the old GDI days.
Any ideas are really welcome.
Create a UserControl containing your display logic (you graphic, for instance). Grab you ViewModel list and project then in UserControls, setting each ViewModel as each UserControl's DataContext.
Force each one to render calling Measure with infinite value and then Arrange with the resulting DesiredHeight and Width. Then follow the procedures to print WPF visuals (link link link).
Essentially, this should be quite simple if and only if your views work independently; i.e. your ViewModel doesn't contain UiElements that are placed into your View.
Simple solution is to basically print your visual root. If need be encapsulate your Views in a user control first.
PrintDialog printDlg = new PrintDialog();
UserControl1 uc = new UserControl1();
printDlg.PrintVisual(uc, "User Control Printing.");
Reference
Alright, I have to admin that I now switched back to doing the printing through code only. I would have really liked doing it "WPF-style" but handling the multiple pages issue was just too much trouble.
Anyway, there is still one issue regarding the printout left but this will be another question.

WPF Canvas - Visual Studio like split view

I'm working on an app, that displayes huge (10000+ elements) graphs in a wpf canvas.
I'd like a feature like in Visual Studio, when you can split the view of an editor (so I can view two distant part of the same graph at the same time).
I have some constraints:
data binding (creating the bindings) of graph elements makes the loading of big graphs very slow, so I'm not using MVVM, the "VM" knows about the view and updates it directly when needed
the children of the canvas are frameworkelements, since I use the Tag property
because of the number of graph elements, I don't want to keep two different view for each element for the two part of the split view
So it should be like displaying multiple parts of the same canvas in different places. You can't set two parents for the FrameworkElements in WPF, so the easiest way is out of question :(
What are my options? Should I reconsider my constraints or there is some workaround for this?
Let me know if you need any more details (it's a big application, so I can't give you every information).
Edit: duplicating with visual brush is not an option since I need proper input event notifications, so both view must be editable.
Options:
Bind the same data to two controls.
Use a visual brush and duplicate input on the real control.
Create a custom graphing control that can output two parts of the graph at once.
If binding to two controls is too slow, then I think you need to rethink your application. The very fact that you have so much data displayed at once that you need a dual view to see separate parts is disturbing. That should raise a red flag. The red flag would notify you that, "What I need, and what I have is different." And you should go back to the drawing board and find out what you really need.
Otherwise, it might be best to create a custom control. The graph is rendering in its entirety even though you only need small portions displayed. If you had your own custom control you could speed up the entire app by rendering only visible portions at a time, and splitting within the control.

MVVM - Closing a tab when a record is deleted

I'm not really sure how to do this in the best MVVM way...
Basically, my main app opens up a search window that shows all records in a TabPanel. Then if a record is double clicked a new tab is opened with that record. Now, I'm trying to keep things MVVM, but I can't for the life of me figure out how to close the gui tabitem when a person deletes the record (why keep it open if the record is gone).
The only way I can figure out how to do it now is to pass the instance of the TabItem as a parameter of the DeleteCommand, which to me seems like a big no-no, but I can't for the life of me figure out how to accomplish this.
If you were going to do this in the true MVVM sense, then double-clicking a record would, behind the scenes, add a record to a collection of records. That record collection is the datasource for the tabs in your control. Simply removing that item from the list (usually an ObservableCollection<T>) would result in the UI updating and the tab being removed.
Which approach are you currently using to show the tab?
Edit (in response to comment):
That is not "true" MVVM. It doesn't matter if the tabs can be more than just records. You should create View Models which abstract those details, then just put your view model instances (RecordViewModel, ReportViewModel, etc) in an observable collection and bind to that. Use datatemplates to render the correct views for each tab's content based on the type of view model the current tab is being bound to.
Josh Smith wrote an amazing article describing how MVVM works. The sample application does something very similar to what you want to do.
The application displays a TabControl which displays 1 or more workspaces. The workspace area displays two different kinds of items. The tab items are closable. Take a look, I'm sure this will solve your problem.
WPF Apps With The Model-View-ViewModel Design Pattern

Rotating windows in WPF

I need to create a WPF application which is maximized and which rotates amongst about 10 different screens. Each screen will take the entire area and show different content.
I already know how to maximize the window with
My question is what is best to put inside that window to achieve what I want?
Ideally I'd be able to have 10 different .xaml files and I just load one after the other to take the entire screen. I'm not sure the best approach for accomplishing this in WPF.
Thank you!
One quick way to do this is to use WPF's built in page navigation. By making your root window a NavigationWindow and each view a class derived from Page (similar to work with to a UserControl or Window) you can just set the NavigationWindow.Source to a relative URI that points to the page you want to show (like a web browser) and simply switch it as needed.
This sounds like a classic MVVM application, which is simply too much to put into detail here. Google MVVM or Model-View-ViewModel, or pick up the book Advanced MVVM by Josh Smith (widely regarded as an expert in such things).
However, this is basically what you are going to have:
One class, the ViewModel, is an abstraction of the data that you need to bind to
Your data Model
A View for each thing you want to show. A View is simply something that holds your UI, be it a DataTemplate or a UserControl. Each View is bound to the ViewModel
The Views are the things that will "rotate" (although rotate in WPF implies animation and/or transformation). How you switch between them is up to you, although it sounds almost like something that would be done with a DispatcherTimer and animation (i.e. like fading between pictures in a slideshow).
This question is really too broad for this forum - you will need to do quite a bit of research on WPF fundamentals before proceeding. Again, MVVM is a good direction to start.
EDIT: Something More Lowbrow, per OP Request
This is probably as simple was you can make it (and still create separate XAML files for each piece of content):
First, create 10 UserControls (XAML files) for the stuff you want to show.
Next, add an instance of each of these user controls to your main window. Set the Visibility of each of these to Collapsed, except the first one to show.
Put a "Next" button on the main window.
In the code-behind, handle the Click event for the Next button. In there, keep track of which UserControl is visible, by name. Set the one that is currently visible to Visibility.Collapsed, and set the next one that is supposed to be visible to Visibility.Visible.
This is certainly an ugly solution, and not very WPF-ish, but it will get the job done.

Resources