WPF Drawing on a ListBox - wpf

In a ListBox derived CustomControl I need to draw lines joining ListBoxItems that are layed out in a Canvas ItemsPanel.
I can achieve this by having class ListBoxLines : UIElement that does drawing in OnRender and then including that object in my ListBox ControlTemplate (but to do that I need to pipe the listbox contents to that class...)
<ControlTemplate TargetType="{x:Type p:NetworkVisualization}">
<Grid>
<p:ListBoxLines/>
<ItemsPresenter/>
</Grid>
</ControlTemplate>
Im just wondering if there is an easer way. Id really just like to add my draw code directly to my ListBox derived class but if I do that it seems to draw UNDER the listbox canvas white background.
Is there any way to to custom listbox drawing directly in my derived listbox class?
EDIT: The motivation for this question is a custom control to display nodes and linkstrengths of a wireless mesh network as in the image below:
EDIT: Additional issue: The OnRender code for ListBoxLines (the node links) is cached - how to force a redraw of this when a node is dragging? Ideally i want to build the cache with the all lines except for the currently dragging nodes lines and only redraw while dragging the lines to that node - not sure how to go about that.

Thanks for updating the question - from the original description we were on completely different pages.
Personally I would not implement a control like this, as I know from prior experience that it is not easy task. In the last two three occasions where I have needed charting I have used middle-ware solutions.
The argument for middleware is an easy case to make:
It will save you significant development time.
You will get results quicker, allowing you focus on your specific requirements.
Even if you choose a commercial provider, the time saved equates to money.
I recently evaluated charting middleware options for a project less than 5 months ago so I can tell your directly that for a WPF application the best libraries are:
Mindscape Diagrams 2 (Commercial)
Chart# (Codeplex Project, Microsoft Public License)
I have used both products for studio applications (internal, however released as if the users were clients).
...
Take a look at the above solutions, come back with further questions (if any) and then if you still want to write your own I will at the very least point you in the direction and resources to do.
A side note, you say that you like the selection part of the ListBox - did you know that the selection functionality is actually supplied by the Selector base class?

Related

WPF Custom Control with Databinding

I'm looking to create a custom control which represents a hand.
This at needs to be bound to a datasource, then if a value/index value is present in the datasource which is representing a particular finger, the finger in question should appear green.
Can anyone point me in the right direction to start of with such control?
Basically I'm creating an app which records which fingers people where their rings and how many.
So graphics on each finger will show Green plus a number showing how many.
Rough Hand Design for User Control
Any help or direction will be mostly appreciative.
I'd recommend a usercontrol rather than custom control for this. As I think that link Clemens posted says, unless you really are going to switch out the template of the control then you don't need to do a custom control - which would be harder than a usercontrol.
This will have at least one dependency property you're going to bind your collection to. Make that an ObservableCollection. You can then pass say 0,1,0,2,0. If people change the rings they wear super dynamically you can set one of the collection to itself to cover change notification to the control.
Inside this I'd put a viewbox with a canvas in it.
Grab an outline of a hand from somewhere. You want to get a geometry out of this so look for a svg preferably.
Maybe https://www.flaticon.com/free-icon/stop-hand-silhouette_57659
Then download and install InkScape.
Use this to trace bitmap if that's all you have then save as > xaml.
Open that file in notepad and you'll see a path with a set of sort of co-ordinates. Grab those. These can be used to define a geometry you use as a resource or directly used as the Data to a path.
I use such a resource for the email "icon" in this:
https://social.technet.microsoft.com/wiki/contents/articles/32610.wpf-layout-lab.aspx
Or you could probably use one of the hand icons from syncfusion's metro studio ( free ) https://www.syncfusion.com/downloads/metrostudio
A Path can be used for your hand.
You then want 5 itemscontrols for your thumbs and fingers.
You could maybe make each of them a usercontrol as well but I'd try 5 controls for a first iteration.
They should template each item they're given into a green rectangle defined in itemtemplate.
Position 5 of them to taste on your hand's digits.
Bind their itemssources by index to your collection and use a converter to return the number of objects specified by that. So if it's 3 then you generate three objects.
That viewbox is there to scale everything. So you can size your control however you like and the rings will stay on the fingers.

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 CustomControl design advice

I need to develope a WPF custom control to show the layout and connectivity of nodes in a wireless mesh network. The user needs to be able to drag the nodes around. The canvas should grown and Scrollbars should appear as required if elements get draged off the available space. The ability to zoom in/out might be required.
My first take on this is to use a ListBox derived CustomControl with a Canvas based ItemsPanelTemplate. To get things moving Im using Josh Smiths DragCanvas that allows UIElements children of the canvas to be dragged around. My "node" class is not currently UIElement derived (the DragCanvas is currently working with the ListBoxItems that wrap my nodes).
1. Is this a bacially sensible approach or should I be abonding the ListBox idea and going something lower level?
2. I have to overlay the inter node link lines - not currently sure how to go about this (as a UIElement class that is part of the ControlTemplate?)
3. A few people seem to be having a headache with scrolbars in Canvases - is this going to be an issue?
Any general or specific advice most appreciated.
Wow, not bad as a control!
I am doing something similar, but it is not so simple.
1) IMHO, the DragCanvas is a basic way to host+drag elements. Since you will have to host labels (nodes), arcs and labels again (arcs' weight), I think the DragCanvas would be harder than write a custom control by yourself.
Not everything comes easy with templating: sometime is much better the "old" approach winforms-like, or even a hybrid way.
2) As stated, I'd create a Canvas-derived panel, which will host several UIElements (labels, arcs, etc). All of them should be governed by a model+viewmodel. That's a bit harder at the beginning, but it will give you a lot of satisfaction and flexibility in the future.
3) I don't think the Canvas will give you any headache! A Canvas full of elements has always a size of zero. That leads "headaches" for those trying to add a scrollviewer.
Instead, the Canvas-derived class (above) should override the MeasureOverride method, so that its size will fit any of the hosted objects. However, it is a bit annoying the fact you cannot use negative coordinates (it will cause scrolling problems).
It's hard to describe in few lines all the work behind a similar "editor". The task isn't easy, and the problems are many.
Hope it helps, anyway.
Cheers

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.

Complex .Net 2.0 Windows Forms control: where to start?

In order to make a convenient UI for an .Net 2.0 Winforms application I am working on, I have need for a control that I'm pretty sure goes beyond the "out of the box" behavior of any standard control. A mock-up of what I'm trying to achieve follows:
Mock up http://www.claware.com/images/temp/mockup.png
Essentially, this part of the application attempts to parse words into syllables from tribal languages (no dictionary to refer to; any and all unicode characters are possible.) By the time the user gets this far, he has already defined the vowels / consonants in his language and some other configuration. There is then an iterative process of (1) the application guesses which syllables exist in the language based on some rules, (2) the user refines the guesses, selecting the correct parsings or manually parsing a word, (3) the application "learns" from the user's feedback and makes smarter guesses, (4) repeat until the data is "good enough" to move on.
The control needs to present each word (the grey headers), then all the syllable break guesses (the white areas with dots separating the parts of words.) There is also a way to manually enter a parsing, which will display a text area and save button (at the bottom of the mockup.) When the user hovers over a guess, the background changes and "accept / reject" buttons appear. Clicking on the accept, or entering a manual parsing, removes the entire word from the list. Clicking the reject button removes just that item.
I'm by no means 100% sold on the formatting I have above, but I think you can get a general idea of the types of formatting and functional control I need. The control will also scroll vertically--there may be thousands of words initially.
My question for you experienced WinForms developers is: where to start? I would really, really like to stay within the .Net core framework and extend an existing control as opposed to a third-party control. (At the risk of starting a religious war: yes, I suffer from NIH-syndrome, but it's a conscious decision based on a lot of quick-fix solutions but long-term problems with 3rd party controls.) Where can I get the most "bang for my bucK" and the least reinventing the wheel? ListView? ListBox? ScrollableControl? Do I need to go all the way back to Control and paint everything manually? I appreciate any help that could be provided!
[Edit] Thanks everyone for the ideas. It seems like the most elegant solution for my purposes is to create a custom control consisting of a FlowLayoutPanel and a VScrollBar. The FlowLayoutPanel can contain instances of the custom controls used for each word. But the FlowLayoutPanel is virtual, i.e. it only contains those instances which are visible (and some "just out of scroll"). The VScrollBar events determine what needs to be loaded. A bit of code to write, but isn't too bad and seems to work well.
I would look at the TableLayoutPanel and FlowLayoutPanel controls. These will let you organize a series of controls with moderate ease in a vertical fashion. I would then create a UserControl that consists of a label and 2 buttons. The UserControl will expose properties like Text and events that are exposed for the button clicks.. For each entry in the list, you will create an instance of the UserControl, assign the text value, and handle the click events. The instance will be placed in the Table/Flow panel in the correct order. Both of those layout panels do allow for inserting items between other items so you can add/remove items from the list dynamically.
Edit:
Given the length of what you are trying to render, I would consider using the DataGridView and do some custom rendering to make it perform how you want it to work. Using the rendering events of the DGV you can merge columns, change background colors (like highlighting the dark gray lines), turn on/off the buttons, and handle changing the grid into edit mode for your rows to allow modification or inserting of new values. This method would easily handle large datasets and you could bind directly to them very easily.
Well, this certainly looks like a candidate for a custom component that you should be creating yourself. You can create this using standard .Net drawing commands along with a text-box, and a regular button control.
Now you want to find out where to start.
Create a Windows Forms Control Library project.
Drop in the textbox and the button control.
The panel drawing code should preferably be done by code. This can be done using the regular GDI+ commands.
Edit:
Here's another idea, and one that I've practically used in my own project with great success.
You could use a web-browser control in the app, and show your data as html. You could update the source of the web-browser control based on the input in the textbox, and clicking on the links in the web browser control will give you the event that you can trap to do some action. Your CSS will work.
I used this technique to build the 'desktop' in an app I made called 'Correct Accounting Software'. People loved the desktop so much that it is one of the best loved features of the app.
Here's how I would do it:
Create a custom control. In this custom control, have a ListBox atop a LinkButton, and when the LinkButton is clicked you can make it give way to a TextBox. The ListBoxes will have the top row unselectable... you can probably get the rest from there. When you get your list of words, fill a Scrollable of some kind with one control for each word:
(foreach String word in words){
myScrollable.add(new MyComponent(word));
}
From there, I'm not sure what you want to do with the boxes or the data, but that's my initial idea on the UI setup.
Use the WebBrowser control and generate the HTML markup into it using DocumentStream or DocumentText.

Resources