Most effecient way to display my data for fast fluid update - c#

I'm still getting to grips with C Sharp and .NET and I am working on an application to display data being continually read from a USB device. I have all the USB code working and it is receiving the data updates every 5ms. The data consists of a set of sensor values for a number of units, say 50 units with 12 sensors per unit.
Currently I am using a ListBox object to display 50 rows of data. I'm setting the listbox mode to OwnerDrawFixed and my datasource to my data array of objects that represents the data read from the USB device (one object per row of the ListBox) and I'm using the DrawItem event to actually graphically draw each row of the list box as requested by the listbox (I'm doing it this way to enable text colouring, formatting, tidy layout etc).
In order to get the ListBox to refresh the data being displayed I'm calling periodically calling Invalidate to force it to redraw, but this is horrendously slow, and flicker unacceptably even at low frequecies such as 1 second updates never mind getting anywhere near the 5ms refresh of the sensors.
Can anyone suggest a better approach to updating the data on screen, perhaps one where I'm not drawing everything everytime or perhaps a way to tell the ListBox to only redraw a single row perhaps if the data on that row has changed?
I'm not tied to a ListBox in anyway, it's just my unfamiliarity with the .Net framework - perhaps the best solution might be to render everything to a bitmap and then blit it to the screen in a single action.
I've already read a similar question but the suggestions in there didn't really help...
c# - fast ListBox data update
Any alternative suggestions from experienced .net developers greatly appreciated...

Inherit the ListBox control and enable double-buffering is, I think, your best bet. I don't know how the ListBox paints but that should reduce flicker.
(If that doesn't work, a hack is to invalidate only a tiny rectangle on the corner and hope it paints properly. That most likely won't work with the original set of controls, though.)

It's very difficult to make a recommendation without knowing what you are doing. You might explain what your "data", "sensor values" and "units" are. In general, graphics are better for showing large data sets than vast lists of numbers.
If this is some kind of transient data, like sound intensity, you might consider a VU-meter kind of display, like in a music player.
If you are trying to track trends or changes, consider a sparkline or graph.
If you are trying to show correlations between data, consider a spectrum or XY graph.

In WPF you can fill ListBox at the beginig and after what just send data to layout acynchronosly.
If its posible use WPF you should try. Code is triviale when you have constant emount of data items.

For those who are interested in the solution that worked for me both solidly flicker free and fast.
I simply use a Panel control to represent my table in the design view, then in my code I have a method which is triggered by a timer every 1ms (though in reality I can't seem to get it faster than every 16ms - which I guess is probably linked to the 60hz vsync refresh of the monitor because I'm doing a graphical blit).
I grab the bounds of the panel, create a bitmap of matching size, draw my data to the bitmap using the various graphics commands (such as DrawString) then I blit the resulting bitmap to the panel control. This works well if I then subsequently resize the window as the panel is resized and my bitmap is accordingly resized.
This also works fast, and in reality is no more work than the previous slow/flickery solution using a list control, however it is to be noted that there is not support for selecting rows etc (as this app was only using a ListBox to display data).
I'm now seriously considering mini techs suggestion for future listbox work as this work around works fantastically well, and subclassing the ListBox (rather than basing it on a Panel control) would allow me to inherit some of the row selection stuff etc.
Thanks for all the suggestions,
Rich

Related

How to initially place WPF controls on dynamic fullscreen application

Alright, so I'm trying to figure out the best way to accomplish this for my rather unique case. I have a fullscreen WPF application where controls are added to a Grid dynamically and the user is given the option to freely move/resize them. The controls can be individually moved or resized anywhere on the parent Grid but I have prevented them from overlapping via their MouseMove events. They also cannot be moved outside of their container. Since the app will be running on machines with different monitor sizes, I need to take that into consideration when making the original layout. I have an initial layout that I would like to use, but it would seem that I'm out of options:
I first tried using rows and columns just to (initially) place the controls that are added. This method places them correctly but becomes a problem when I need to move or resize the elements because the control is already assigned to a particular row and column. I could try to use this method and then remove any rows/columns after placing the controls, but I don't think that would work well.
I've also considered a Viewbox, but that's not practical in my case for fairly obvious reasons (as it merely resizes the controls to fit the screen). I'd prefer not to use this because I would only need it to standardize my initial layout. That's it. I also don't want to mess up any text that will be displayed on the window.
So yeah, this is more of a "best practice" question because any solution I can think of would not look very professional or elegant. Feel free to ask any questions if you need clarification.
Edit: As an additional note, I'd prefer to stick with a Grid as opposed to a Canvas as my container.
Edit 2: Just to be clear, I would not need the specific (inital) layout after the first launch. When the program exits, the layout (Margins, Width & Heights, etc. for each element) is saved to a file to use for the next launch.
I've developed a number of kiosk/interactive applications using WPF. If you are trying to show the element transitions (while moving), then it might be best to use a parent Canvas and bind the Canvas.Left and Canvas.Top properties. You can mimic the grid alignment, using a Canvas, if you put in place mechanisms (e.g. Manipulation/Mouse events, converters) to make sure that the Canvas attached properties adjust to the row/column offsets.
It is not uncommon at all to use the Viewbox to mitigate display differences (and your use case is not "rather unique"). You set the Viewbox to a target resolution (e.g. 1920x1080) and allow the control to fill the available space. The other alternative would be to dynamically apply a content template based on the application window size/ratio.
After looking at multiple options, I've decided to just use a calculation to (sort of) simulate the behavior of rows/columns. Because my application is fullscreen, I can take my SystemParameters.PrimaryScreenWidth and SystemParameters.PrimaryScreenHeight to orient my layout. Using a combination of universal padding (static values) and ratio-based calculations (dynamic values), I can smoothly set my initial layout.
For instance, I'm dividing the width of my monitor by 6 (rounded up to avoid decimals) and using that (minus half the control's width) as the control's Margin.Left property, centering it on a 'column' of sorts.
Honestly, my initial layout is fairly simple right now, so we'll see if this will suffice going forward. Thanks to everyone who contributed to the question, and sorry if I was unclear on what I was asking.

C# redraw only foreground

I'm working on a college project (simulation) that needs to draw a lot of lines and objects to a custom UserControl. My current approach is just to redraw everything for every tick / update loop using Invalidate(). But it sure needs a lot of time to draw (which is resulting in very low FPS) especially when I need to draw thousands of lines and rectangles.
So how can I only re-draw a specific (group of) objects that move in every update loop and only re-draw the rest (the rarely updated objects) when needed? Or is there other way to optimize the way I draw in this problem?
My idea would be the following:
Draw your Control onto a Bitmap (or other image format) once, and save that Image. Then display that Bitmap on your Control. (Assuming you use a Control that can do that, i.e an ImageBox, not sure what would be best for that).
Whenever you update your graphic, keep track of what sections of your Control may be outdated, then redraw only these sections (drawing only the objects that touch that section), and copy the other sections from your saved image.
Display (and save) the new Image.

Implementing scrollable table on Windows Phone

I need to create an app for TV guide. Requirement is that UI must be a copy of one you can see here: raspored.bnet.hr. As you can see, there's a lot of data. So, basically it would be a large scrollable table. Since there is no such UI control as table on Windows Phone, I found out that the best approach would be to create one vertical listbox with horizontal listboxes as its items. This is all ok and I'm able to create it. But, to make it behave like a table I also need to make these horizontal listboxes scroll in sync, not to scroll one row at a time. Then I disabled horizontal scroll on horizontal listboxes, and enabled it on the parent (vertical) listbox and while it gave the result I wanted to achieve one big problem came up - UI virtualization. I know ListBox has UI virtualization enabled by default and I can see it while scrolling on vertical listbox, but when I disable horizontal scroll on horizontal listboxes, performance is really bad, and sometimes there's an OutOfMemoryException. I understand why this happens because when I disabled horizontal scroll, those listboxes didn't know which items are on screen anymore, so the loaded all of them into memory.
What I also tried is to leave scroll on every listbox so they have UI virtualization, and then place ScrollViewer above them. Then I tried to listen on Manipulation events on scrollviewer and progamatically scroll all of the listboxes as needed. This didn't work good, first of all ManipulationDelta event doesn't appear to fire frequently enough to make scrolling smooth, and I think there could be a performance problem with calling ScrollToHorizontalOffset on ~180 listboxes.
I also tried the LongListSelector from WP8 as I read that it has much better UI virtualization and should be used instead of ListBox. The problem with this is that I couldn't make it scroll horizontally. Is it possible at all? I tried to wrap it into ScrollViewer which can scroll horizontally and it's working, but only if I set fixed width on LLS.
I also tried Telerik's RadDataBoundListBox and the problem was similar, I can't get both horizontal and vertical scrolls on the same listbox. So I could only get that each list scrolls on its own.
Can someone tell me if they had similar situation and what would be the best approach to solve this? I believe I'm not the only one that has this requirement to implement large scrollable table.
Thanks
UPDATE:
I'll just inform you that I didn't find a proper way to implement this, instead I've done it in HTML with WebBrowser control. Seems like IE already has UI virtualization implemented so it can work with large pages very well.
May be in your listbox there are images? and Out of memory Execption will occur you can do 2 things:
Don't load data in one time use BackgroundWorker
Have one local image in the App of the image you are downloading and set it as default image & when you scroll to some 50 values in forward clean the image Url to local and when it comes back give again the image url you want to show .
Because i have used it to scroll around 20k values.

C#: Set ComboBox Height

I'm trying to set the Height of a ComboBox in C#.NET CF / WinCE6.
So far I managed to do it by using the MessageWindow.SendMessage() with CB_SETITEMHEIGHT. The issue is the ComboBox gets to its initial Height when being clicked.
Is there a workaround for this ?
LE: How would this affect performance, considering the ComboBox might store 1k entries ?
Thanks.
One thing you could do to overcome the resetting of the combo box height is to set your SendMessage solution on a timer, say once every 250ms or something like that.
Btw, are you talking about DropDownHeight or the actual control's height? If it's the latter you can actually resize it by increasing the size of the font. That's what the combo box' size is keyed on and why you're losing that dimension upon interaction with it.
But your plan to store 1k entries in a combo box on a handheld device is a usability issue. It's hard to pick things out of a list on a combo box when there are few items to choose from. If you put 1k items into the list you will be forcing the user to scroll which is a very tough thing to do even for experienced Windows users due to the size of the scroller, the stylus and the weird nature of some of the touch screens out there. You should think about a filtering process whereby you limit the number of items in the combo box by several orders of magnitude.

handling orientation changes effectively for all controls with small code change

I have a Windows Mobile project built in C#.
I have a lot of ready made forms having various controls on it, from Listviews to Editfields.
When user changes orientation some elements are not refreshing correctly. For example the Listview's columns are same and doesn't accommodate the new screen width change (scrollbars appear or half of the screen is filled).
How do you handle these changes?
Do I need to call for each form these fixes by hand, or I can create some kind of global way to fix this? I would like to go with the simplest method if possible.
I would like to avoid the classic way, to add code to all of my forms. So I am looking for better ways, and I would like to see more ideas.
I'm assuming that most of your controls are using a DockStyle, and that will get you 90% of the way in terms of updating the GUI on orientation changes. For the ListView, you'll have to add in some code.
You can add an event handler on Form.Resize, and there put in code to resize the ListView columns. You can tell portrait vs landscape by comparing width vs height. There's also a way to add an event handler on an actual orientation change, but it's interop and I don't remember the code offhand. Form.Resize should be sufficient for most cases.
You can check out an example here

Categories