I'm trying to improve the real-time log display of a rather complicated system. Currently there is a significant tradeoff between situational awareness (improved by displaying only high-level events) and reproducibility (which requires lots and lots of details). The obvious approach is to structure the details as a tree and allow their display to be expanded and collapsed.
The existing implementation uses just a RichTextbox. I'd like to use MVVM for my rewrite, not only because it's a best practice but also to enable behavior such as "Show details of an operation while it is ongoing, then automatically collapse them once it has successfully completed.".
As a further complication, the log records have some structure, which needs to be displayed in a columnar format. The nesting should be accomplished using the description column only (can be through pure indentation, as depicted, or using tree lines).
Can you recommend a way to map this data structure onto WPF template elements? There doesn't seem to be a way to produce a sequence of DataGridRow objects from a parent object. And because the rows do not have uniform height (some of the detail data is multiline), trying to use a WPF tree for the description and then synchronize the vertical placement of data in other columns doesn't seem feasible.
Will I have to give up on the idea of a data-bound model, and use more of a view-controller design with manual creation of WPF elements, with references to these elements such as DataGridRow stored explicitly within the in-memory tree structure, and implement collapsing and expanding by iterating through the child items and updating each descendant's Height property of the associated WPF element object?
And if I do break the data/presentation wall and use imperative coding style, is there something similar to WinForms SuspendLayout/ResumeLayout that I can use to achieve just a single layout pass per collapse, no matter how many rows changed in height?
Here is a quick mockup of the tree structure made using WPF+XAML. It's just a Grid without any document structure -- all the text elements are direct children of the Grid with manually set Grid.Row and Grid.Column attached properties. Clearly that would not be suitable for an implementation with new data and structure being generated in real time.
Related
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.
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.
I have always been using a Syncfusion virtual grid which works on the basis of an override on that grid that is fired for each cell that is visible! It provides me with information on the row and column and some cell object that lets me set the value of that cell, its formatting, colours etc.
This allowed for very fast scrolling on very large datasets, since I simply have to 'read out' the value like dataSet.Tables[0].Rows[1000000]["LastName"].ToString()
Is there anything similar exposed by the WPF DataGrid?
EDIT
I need to make myself clearer - I know about virtualization and that it switches itself off when you do grouping etc. Having run a test with grouping enabled over a dataset of 20,000
rows made my grid choke on itself.
Therefore my previous question stands on its own!
Is there any way the grid allows me to fill in the text and do some formatting through some override or callback?
Thanks
The DataGrid uses virtualization by default. This works by either creating and deleting cells on the fly or by recycling the visible cells and repopulating them with the current row's data. This can be turned off as well as tweaked by playing with the 'VirtualizingStackPanel.VirtualizationMode' property and is forced off in many situations (grouping is a good example). This virtualization can be a godsend and a curse. If you have a simple set of requirements, then it makes it dead easy to get good performance. If on the other hand you are doing complex runtime binding, including triggers and custom columns, then it becomes a bit of a nightmare.
a couple of important reads:
http://msdn.microsoft.com/en-us/library/cc716879.aspx
http://msdn.microsoft.com/en-us/library/system.windows.controls.virtualizingstackpanel.aspx
Complex visual trees are nice when designing views as they allow you to create a structure in XAML closely matching the logical structure of what you are modeling. They are however not great for performance, using a lot of nested panels with layout such as grids will reduce performance when adding and rendering views.
Is there a tool that can "render" a XAML control, either at compile time, creating an equivalent but flat XAML file (given a specified size), or at runtime, doing the same thing given an instance of a control? Are there any other ways to accomplish a similar thing (other than setting the CacheMode)?
I don't think so. Essentially, as far as I know, the most efficient way to model any layout is to use a grid with a very large number of columns and rows. A Grid can achieve anything else you do in SL/WPF (supposedly), so your answer in terms of efficiency would be to nest less and use one large Grid.
My company's product is, at its core, a framework for developing metadata-driven UIs. I don't know how to characterize it less succinctly than that, and hope I won't need to for purposes of this question, but we'll see.
I've been trying to come up to speed on WPF, and have been building UI prototypes here and there, and recently I decided to see if I could use Expression Blend to help with the design of these UIs. And I'm pretty mystified at this point.
It appears to me as though Expresssion Blend is designed with the expectation that you already know all of the objects that are going to be present in the UI at design time. But our program generates these object dynamically at runtime.
For instance, a data row might be presented in a horizontal StackPanel containing alternating TextBlocks (for captions) and TextBoxes (for data fields). The number of these objects depends on metadata about the number of columns in the data row. I can, pretty readily, write code that runs through a metadata record and populates a StackPanel dynamically, setting up the binding of all of the controls to properties in either the data or metadata. (A TextBox's Width might be bound to metadata, while its Text is bound to data.)
But I can't even begin to figure out how to do something like this in Expression Blend. I can manually create all these controls, so that I have a set of controls that I can apply styles to and work out the visual design of the app, but it's really a pain to do this.
I can write code that goes through my data model and emits XAML for all these controls, I suppose, and then copy and paste it. But I'm going to feel really stupid if it turns out there a way to do this sort of thing in Expression Blend and I've dropped back and punted because I'm too dim to figure out the right way to think of it.
Is this enough information for someone to try formulating an answer?
I think expression blend is a very good choice ESPECIALLY if you want to design dynamic, datadriven UIs. You can use Blend to desgin DataTemplates that define how a single dataobject is to be presented to the screen. For example, if you have an object of type Person you can define the controls like textboxes, border etc. that then are to be generated automatically for each Person in your list.
You can then fill your ItemsControls (DataGrid, ListView, TreeView ...) with those dynamic databojects and WPF knows how to render them. If a Persopn is removed form the list, the generated visual item will be removed too. This is just a simple example the whole notion of dynamic data is deeply baked into WPF and you can access these features using blend.
To be able to design the datatemplates in expression blend you need to provide sample designtime data.
Also to be effective with all this it is of high advantage if you stick with the MVVM design.