WPF: Getting a list box to stay put - wpf

I have this situation where I have a ListBox which is being populated from a background thread (it's an address book and the data is coming from AD).
The problem is that since the list is sorted (using CollectionViewSource) and also available to the user while more data is being retrieved, it's bouncing all over the place as new items are being inserted at various places in the list. So it's available to the user, but mostly unusable since the user's selections keep going out of view.
Is there a way to keep Focus to the item selected, and preserve the selection, even if items are being inserted above and below the selection from the background thread? I would prefer not to sort on the server, which I understand can be a bad thing when it comes to AD.

I'm going to respond to this from a UI design perspective rather then a technical code perspective. (I'm sure someone else will have a way to have the list box keep the selected item in view)
I would argue that the use of a list box while large ammounts of data is being added to it is fairly impossible to do nicely. Lets just say you do get it to keep the selection in view, what about while the user is still searching for their required item, you wouldn't be able to keep it still then.
Firstly if the expected total load time is under 10 seconds you could just disable the list box until loading is finished. (Obviously grey it out with a spinning animation or something so the user can see it's doing something.) I'm assuming you have already dismissed this option otherwise you probably wouldn't be asking here. But I do think this is worth considering. If the load time is farily small consider if your users will really gain anything by being able to browse the list while it is still being loaded.
Secondly, I would propose that you find a way to restrict the contents of the list box so that only small quantities are every displayed at one time. You could do this by only displaying names starting with a single letter of the alphabet (along with a letter selection control). Or you could provide a filter entry text box at the top where the user could type the first few letters and the list box would only display the names starting with those letters. This would allow the user to type say "sa" and the list box would display "sam", "samantha", "sacha", etc. Now you only have a small number of items in the list so you don't have to worry about it jumping around. If the number of items in the list grows too large (because of the loading on the background thread) and the list goes beyond the height of the box the user can simply type an extra letter to futher filter the list.
Sorry if this isn't really what you wanted, but I thought it would be worth bringing alternative design up incase you'd overlooked it.

Related

Make ComboBox Search List as User Types

I have been researching this for weeks now, and have not been able to locate what should be a simple solution to a simple problem. I have an Adobe Pro XI form with a ComboBox that has a very large list -- over 500 -- for the user to select from. Currently, the ComboBox only responds to the first letter typed, so that if the name the user is looking for begins "Lor...", when the "L" is pressed it will scroll to the top of the "L's", but then when the "o" is pressed, it scrolls to the top of the "o's", and so-on. Is there an easy solution to script this so that it will scroll through the list as the user types? Optimally, I'd like to be able to use a Document level script that I can then activate On Focus from the Actions tab of the ComboBox Properties dialog. I have found some solutions to this problem for other applications, but have not been able to find something that works for Adobe Acrobat Pro. Note that I am not a programmer, I am the company accountant and am trying to fix a form. Thanks for any help.
Combo boxes become rather cumbersome when they have a high number of entries (in older References, it was suggested to not go beyond 50 or so entries).
It does require a little bit more programming, but using a popup in this situation, together with a field in which the result will be written, is more efficient and ergonomic, because popups can be multilevel, which means, you could group everything between A and D in one level, everything between E and H, and so on.
Have a look at app.popupMenuEx() in the Acrobat JavaScript documentation.
FWIW, with a little bit more scripting, such multilevel popups can be created dynamically on the fly; personal experience shows that to build up such a popup with no more than 35 selections at the farthest level, and a total of 1500 or so selections takes less than a second.

DataGrid row request patterns with data virtualization

I implemented a data virtualization solution using some ideas from CodePlex and the blog of Bea Stollnitz and Vincent Da Ven Berhge's paper (same link). However I needed a different approach so I decided to write my own solution.
I am using a DataGrid to display about a million rows with this solution. I am using UI virtualization as well. My solution is feasible, but I experience some weird behavior in certain situations on how the DataGrid requests data from its source.
About the solution
I ended up writing a list which does all the heavy work. It is a generic class named VirtualList<T>. It implements the ICollectionViewFactory interface, so the collection view creation mechanism can create a VirtualListCollectionView<T> instance to wrap it. This class inherits from ListCollectionView. I did not follow the suggestions to write my own ICollectionView implementation. Inheriting seems to work fine as well.
The VirtualList<T> splits the whole data into pages. It gets the total item count and every time the DataGrid requests for a row via the list indexer it loads the appropriate page or returns it from the cache. The pages are recycled inside and a DispatcherTimer disposes unused pages in idle time.
Data request patterns
The first thing I learned, that VirtualList<T> should implement IList (non generic). Otherwise the ItemsControl will treat it as an IEnumerable and query/enumerate all the rows. This is logical, since the DataGrid is not type safe, so it cannot use the IList<T> interface.
The row with 0 index is frequently asked by the DataGrid. It is seem to be used for visual item measurement (according to the call stack). So, I simply cache this one.
The caching mechanism inside the DataGrid uses a predictable pattern to query the rows it shows. First it asks for the visible rows from top to bottom (two times for every row), then it queries a couple of rows (depending on the size of the visible area) before the visible area (including the first visible row) in a descending order so, from bottom to top. After that it requests for a same amount of rows after the visible rows (including the last visible row) from top to bottom.
If the visible row indexes are 4,5,6. The data request would be: 4,4,5,5,6,6,4,3,2,1,6,7,8,9.
If my page size is properly set, I can serve all these requests from the current and previously loaded page.
If CanSelectMultipleItems is True and the user selects multiple items using the SHIFT button or mouse drag, the DataGrid enumerates all the rows from the beginning of the list to the end of the selection. This enumeration happens via the IEnumerable interface regardless of that IList is implemented or not.
If the selected row is not visible and the current visible area is "far" from the selected row, sometimes DataGrid starts requesting all the items, from the selected row to the end of the visible area. Including all the rows in between which are not even visible. I could not figure out the exact pattern of this behavior. Maybe my implementation is the reason for that.
My questions
I am wondering, why the DataGrid requests for non visible rows, since those rows will be requested again when become visible?
Why is it necessary to request every row two or three times?
Can anyone tell me how to make the DataGrid not to use IEnumerable, except turning off multiple item selection?
I at least found some way to fool the VirtualList. You can read it here.
If you have found another solution (that is even better than mine), please tell me!

Best way to display realtime queue data from database in grid

I have a client-server VB.NET/SQL2008 application which, among other things, keeps track of people who are waiting in a queue. The records for the queue are all updated via the application but they are added/removed on different workstations.
I need to display the queue of people in a grid (could do a multi column listbox if it would add any benefit) and have it automagically update when the queue changes. I don't need it to be real-real-time but I would like the people to show up within a few seconds. I currently have a datagrid bound to the data and I have a timer which is refreshing the datagrid every few seconds. However I'm thinking there must be a better way to do it.
The one thing I don't like is how the grid flickers when it refreshes and if someone double-clicks to select a record exactly as it's refreshing it selects the first person in the list and not the one selected.
I've done some research and it seems like one option is SQL Dependency - however from what I've seen people say it's difficult to set up and get working and "fragile".
Any help is appreciated!

Problems with page layout in Oracle Apex

I'm trying to solve a formatting issue I'm having with Oracle Apex. Overall, this is a fantastic tool for whipping up proof-of-concept type applications, but whenever it comes to "prettying up" a page, it seems to be very difficult to work around.
I have a simple form-based page based on a table. However, I'd like to do a few simple things like group certain fields together on the form (phone info), perhaps throw an image in etc. I can't see any way to do either of these things inside a form. For example, here is an example page
and here are the small changes I want to make (photoshopped):
What the heck am I missing here? I can't seem to add anything except database fields inside the form to visually change things.
Any help appreciated.
It can be done - see this demo (I took the liberty of copying your icon, hope you don't mind). It looks like this:
How it was done
1) I uploaded the image into Apex. (Alternatively it can be hosted elsewhere).
2) I created a page item of type "Display Image" with attributes as follows:
Note the use of rowspan=3 in two places (circled in yellow), to make the picture and its (blank) label occupy 3 rows of the HTML table Apex uses for layout.
3) I created a page item of type "Stop and start table" and put it after the Mailing Address item. This prevents the phone icon taking up the same horizontal space as the name and mailing address, resulting in phone items being pushed too far to the right.
4) I set the "Begin on new line" property of the first phone item to "No" so that it appears to the right of the icon. The remaining phone items have "Yes" so that they appear below the first.

Best way to show screens to user on application

I'm developing a Winforms application which has been running for years with an explorer view (TreeView left, screen right). I means that:
All the screens have an hierarchy organization
All the nodes on TreeView have one and only one screen related.
A screen gets activated when a node on treeview gets selected.
One of the advantages is that the user has an ordered stucture and one of the inconveniencies is that with hundreds of screens the user gets confused.
I see other options: use classical menus, use tabs or a mix of everything.
Any advice for a good way to show a lot of screens to user in a user-friendly way?
Update: I'm changed "hundreds screens" by "a lot of screens". The most important thing is not show all at time but that the user can find what they need easily.
Update2: In this proposal, the user only see one screen at time.
Update3: I'm talking about handling multiple screens not showing multiple screens. No MDI, only one ontime.
I have used other applications similar to this is the past, and the major problem is trying to find the exact screen you want. There are two common solutions to this problem, shortcut codes and favorites menu.
With the shortcut codes, allocate a short code (5 or 6 characters) to each screen. The user then inputs this shortcut code into a text box which will then jump to the correct screen. Users will create their own list of often used codes.
For the favorites menu, allow users the ability to be able to create their own menu list in the structure they want. They will find things easier, if they organize it themselves.
Why do you need to show so many seprate screens at once? Why not just show the screen for the currnetly selected node, why are all needed at once?
If it is all tabular data is is probably too much to be consumed all at once, if it is graphical data, could it not be combined?
There may be a valid reason to show all the data at once or there may not, hard to tell from what is provided in your question. With that said, better to keep it simple than overload the user. MDI apps are never easy to use.
Tabs may work for a small set of items but still is not a good UI for hundreds of items.
If you are only showing one element at a time, out of hundreds possible on the tree nodes, then that is fine. The one screen showing at a time would be contextual to the item selected as the user moves through the nodes. Think of the Outlook approach where what is selected in the left pane is displayed in the right pane in whatever form fits the data being displayed.
Have you considered the Office Ribbon?
The Ribbon gives you a lot of flexibility on how to show and
organize functions and it's highly visual.
Here is a good link about the Ribbon and also here
To use the Ribbon you have to license it from Microsoft. You can do that online.
Providing the user with ketboard shotcuts is usually a good thing too.
I also like to provide the user with an "autocomplete" field on the menu
so that they can can find the function by name (or part of it) and be
able to navigate directly to where they want to go.
I general I find trees to be a bad idea, especially if your "hierarchy" is of a small fixed depth.
If you have a small fixed depth, consider replacing the tree with a list. At the top of the list can be drop-downs for filtering based on the node-level properties. It will use up less screen real-estate because it is vertical-only, with no horizontal component.
Clicking on an item can display it in the view (like currently), but it may be a good idea to allow a user to double-click on more than one item which could launch more windows, or tile with the existing displayed items. (I am assuming that currently, the user only sees a single detailed view at once in any given window.)
Actually, it’s hard to beat a hierarchy for organizing large numbers of items. I wouldn’t favor a classical pulldown menu for vast numbers of windows because it would be even harder to keep track of where you are than in a tree (e.g., a tree lets you look in multiple branches at once). But here’s a few alternatives:
I’m not clear how you ended up with so many windows, but maybe it comes from combinations of classes, views, content, and detail, or maybe it comes from using a task-centered UI structure for something far too complex (I’ve more on that at http://www.zuschlogin.com/?p=3). For complex apps, you want a different primary window for each significant class of data object (e.g., invoices, employees). These are listed on one menu, and typically there’s few enough (15 or less) that it can be single non-cascading pulldown menu. The content of each window is set by a separate menu, perhaps by a menu item that opens a dialog that may include a list box (like an Open dialog) or other controls for querying/searching. The “view” of each window (how the data objects are shown, e.g., table versus form) is set by menu items in the View menu. Details for any given object in a window can be shown in a separate pane within the window in a master-detail relation, essentially turning you data objects into a menu for details. A single window can have multiple detail panes for the user to open and close to select the specific detail to show. Tabs may also be used within a single pane to fit subdivisions of content.
You say it’s not important to show all window options at once, but often showing all options at once makes it easiest for users to find what they need. Maybe you need a “home” window that lists all the other windows in organized, labeled, and separated categories. This is will be easier to use than the tree if your users select a window then stick with it for most of the session. Your tree is better if there's frequently selection of windows throughout the session, owing to the overhead of getting to the home window. If all windows/options don’t fit on a single home window, then show only selected common windows for each category on the home window and provide a button or link to show an exhaustive list.
If you’re talking 100’s of windows, maybe you should have Search, perhaps in addition to a menu-based browse approach to getting to a window.
In any case, providing easy access to the few most commonly used windows is a good idea. Such windows can be explicitly selected by the designer, based on user research, or selected by the the user (favorites), but it also typically works well to make it automatic with an algorithm that uses some combination of frequency and recency of use.

Resources