I'm using an TreeListView (a sub type of ObjectListView) in my current project. Each item in the list is given an icon, but the icon my vary depending on the state of the item. For example if the item is readonly I want to use an icon with a little lock symbol.
When the items are first added to the TreeListView the icons are show correctly, yet later when the state of an item changes the icons are not updating. How do I force the control to regenerate all the icons?
Since the icon is gotten when the ImageGetter for the first column is called, and since that is only called typically when the rows regenerate, then it seems like you could simply call BuildList and force all rows to rebuild. This might be expensive, though, depending on the complexity and number of rows.
A better solution, if possible, would be to call RefreshItem or RefreshObject as soon as you know data has changed. This requires you to know either the specific OLVListItem (rows) that need their icons updated, or the underlying model objects that changed (and thus would cause the icon to differ were its associated rows rebuilt).
Related
I am not sure combobox would be the best vehicle for tackling this problem, but visually it is appealing.
Consider such data as angle -- I could enter its value in radians (single editbox) or in form of degree, minute, second, millisecond (4 editboxes) -- there are other representations, but those two will suffice here. For now I have combobox with mode entries "radians", "DMS" changing mode shows/hides appropriate control.
This approach has two flaws -- it takes a bit more space (for extra combobox with modes), and since each control is different is size everything on right of it moves.
So I am thinking about more direct approach, instead selecting mode, which in turns switches visibility of given control, would it be possible to put each control inside combobox, and combobox would then select that control. The target data would be exactly the same for each row (angle), but each row would have different control, because each row would mean different representation.
Is doable with combobox or am I banging at the wrong door? If combobox is suitable for this task, how to do it?
I was so focused on data binding at the combobox level that I didn't notice that the solution uses the basics of combobox.
So first, for the moment forget about combobox binding to anything -- simply per each row define ComboBoxItem and put any control you like. In effect you will get multiple controls for the same data.
At this point the only missing part is selecting the mode. Since I no longer rely on manually switching visibility of the controls (combobox does it automatically) then I can bind to SelectedIndex and convert it only fly back and forth to mode.
Please note combobox is not bound per se to the actual data (angle in this case).
I have an ObservableCollection that is wrapped by a ListCollectionView.
The ListCollectionView is displayed in a grid (XamDataGrid).
When I add items to my observable collection those items are exposed by the ListViewCollection sorted in the order defined by the SortDescriptions property.
Here's the problem. I would like new items to appear at the bottom of my grid even though the existing ones are currently sorted. Next time the user sorts (by clicking at the column header) the new items should be sorted.
I'm struggling to find a solution to this problem. Anyone's had a similar issue?
Solution A: Manage the sorting yourself behind the scenes
Easiest thing to do here is sort the data behind the scenes (you can use LINQ for that), then assign it to the grid without the sort descriptions. Then as you add items, they'll just appear at the end of the collection. When you click on a header, intercept that and sort yourself accordingly.
Solution B: Add another SortDescription
Another approach is to add another property to your data and create a primary sort on that field first, then by what you actually want to sort on. For instance, you could add a boolean called existedBeforeSort. If you can't modify your model, you can do it via an extension where you store the actual value in a dictionary keyed on the object itself. (That's sort of how DependencyProperties work, but this can be for any object since you're managing the storage.)
Now, in the grid, as you click a sort header, the first thing you do is set the existedBeforeSort property on all items to true. Since your first SortDescription is based on that field, followed by the sort descriptions generated by clicking on the headers, all newly added items will appear at the bottom as you wanted.
The trick to this second approach is making sure as you click on sort headers, you manually make sure your SortDescription based on your existedBeforeSort property is always inserted first. In essence, you're hijacking the implied SortDescriptions and injecting yours to supersede theirs. Shouldn't be too difficult though.
Hope this helps!
I am wondering what the actual design purpose of the CacheVirtualItems event is for when using a ListView in virtualmode. So far most of the examples I can find online are for purposes like when clicking Next on a list of data in an online page and what not.
If I have a fixed List of ListViewItems that are loaded manually by the user and the items will always be kept in the collection no matter what, should I even be using the cache event at all? It's not like I will be generating new ListViewItems per scroll. Should I be fine design pattern-wise without handling the event on a fixed collection of ListViewItems?
No, if you are holding the entire list in memory then there is no need to respond to CacheVirtualItems. It is merely a hint that you can use to improve efficiency.
The CacheVirtualItemsEventArgs argument supplies an index range, allowing you to efficiently load just that range into memory in a single operation. This avoids having either to load the entire list or to load individual items one at a time.
I've put together a scheduling application similar in style to that found in outlook, however it can show the schedules of multiple people. I have written a user control, basically a Border with gradient filled background & TextBlock. One of these controls are added to a Canvas at a set location for every appointment. The trouble is, I will have multiple users, with multiple appointments and may need to display 1000 or so appointments at a time. Initially, it takes an absolute age to instantiate all of these objects, however, I can live with this.
Unfortunately, the big problem arises when I try to scroll through the appointments. I have a couple of buttons to scroll left and right and upon clicking these, the UserControls' Left position are moved left or right a certain number of pixels - it can take several seconds between clicking a button and repainting(I also tried with labels just to test, but it was the same).
I guess the real question here is how to implement an interface, showing hundreds of controls with adequate performance and if this isn't achievable, how would I approach such an UI.
One possible option is a TextBlock CustomControl. You can get the exact same style as you have in your usercontrol but with a somewhat faster loading time.
Without a good, minimal, complete code example that reliably reproduces the problem, it will be difficult if not impossible to completely understand the performance problem you are having, never mind provide a solution.
That said, from your description it sounds like you are really looking to present the user with some type of ItemsControl, such as ListBox or ListView (a specialization of ListBox). In an ItemsControl, you can specify an ItemTemplate that defines how each item in the list will appear; this is analogous to the UserControl you apparently are using now.
I believe it's likely it will work fine just with that change alone. I.e. define your per-item visual as a DataTemplate instead of a UserControl, and set the ItemTemplate property of e.g. your ListBox to that template, then just bind your collection of appointment objects to the ListBox.ItemsSource property.
Note that the ListBox class already defaults to using VirtualizingStackPanel in its ItemsPanel template. So you should have no performance problems at all with this approach if you use ListBox.
If you want to use a different ItemsControl or create a custom one, you may or may not find that you need to use a virtualizing panel object explicitly (such as the VirtualizingStackPanel that ListBox uses). With just 1000 items in the list, even a non-virtualized panel may be fine, but if not then even when not using ListBox, you can always specify it explicitly.
I know this is a stupid question, I need to let you guys know that I am fully aware that it is useless in 99% of situations to make a listbox with this many elements in c#:
That being said I need this to be done...is there any way to populate a listbox with 40000 elements without it completely destroying performance/freezing up, thanks!
note: I have tried it, this is per the exact requirements of a professor...when adding 40000 elements through a DataSource and DataBind the application freezes up
You tell me.
for(i=0;i<40000;i++)
{
listBox1.Items.Add("click me");
}
Even if is possible (I never tried it), the usability for this form will be 0.
In that cases a more usable implementation is via lookup text-boxes and lists, where the user can enter a text to search record that matches this text and displays them in a any kind of list.
It is of course possible to do it, but not very practicable.
When using a desktop technology like WinForms or WPF, for a large number of items like this you are better off using something like an auto complete textbox, and have it set to filter/search after the user has typed two or three characters. In this case you can also use a control that offers scrolling virtualisation - this means that there is only a limited number of UI elements created in the scrolling portion of the dropdown, and those elements get reused when a scroll occurs. If you don't use virtualisation then a new element gets created for every list item that gets scrolled in to view. (Note that Silverlight controls have this functionality - just in case it's an option).
For ASP.NET though I would suggest that you do not want to do anything that would cause a large transfer of data (large items, or small items but lots of them) as it won't be performant. Instead you should look to do what Google does - retrieve search results in a paged fashion.