I am currently on the topic of creating a Combobox that expands with a full treeview where one can select a topic
It is for category selection.
The current approach just displays all "expanded" upfront with different margin depending on which level they are (utilized using itemcontainerstyle margin and a converter)
However, that is not what I want it to be as it tends to grows extremely large with larger category trees
Thus I am searching for other solutions
I could write a custom control but I also face issues in understanding how the selector controls actually get build
Thus my questions are:
Is there a way to get a combobox having a treeview for selecting instead of an itemscontrol?
If no, how to implement the selector properly (could also just derive from control and build it myself, but that would require more work and casting the control to selector etc. would not be possible --> some attached properties are not working then)
Related
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 have integrated a feature in my tool that allows me to expand all recursively. I realise this would generally be a slow process anyway but currently. I have maybe 100 nested controls which are all expanded at once, so calling Expand All means that each control/datatemplate etc is processed at once.
This causes the tool to lock up for a good 10 seconds before responding. Of course, once the view hierarchy has been constructed, its then fast (I can collapse and expand instantly from then on). But it seems a little odd that there isn't a faster way to generate large forms, I wouldn't consider 100-500~ controls very many.
I have looked into virtualisation, but it doesn't appear to be useful to me in this case because all controls are expanded at once. Its fine if I expand them on a singular basis.
Edit:
Updates we're needed to the question to describe what the layout of my window is:
I have a number of TextBoxes, ComboBoxes, Sliders which are all nested inside of a number of Expanders. Each expander can contain N number of expanders, this is recursive to an extent. Depending on how the data is laid out. Some of these data types (which are represented by datatemplates) may contain StackPanels if needed and numerous grids for layouts.
To expand all it simply means to iterate each expander (which IsExpanded is bound to an IsExpanded property). I set this property on each data type (and its children) to true. And let the binding do the work of expanding everything. This causes every single control to be added at once.
Thanks
So after reading the edited question, I have a guess what's going on:
The UI is busy on rendering controls. And I assume there's not much data kept behind in viewmodels bound, so the data is not the point in your issue.
When the Expander control gets IsExpanded = true the first time, Xaml is parsed (object / resource parsing, not compiling) and visual tree children are created.
100-500 visual tree elements is a high number for rendering, because each of them (if it's belonging to the System.Windows.Controls namespace) consists of many sub-controls (Border, Grids, TextBox,..).
What you can achieve is NOT shortening the expanding time, but to unblock the UI:
advise the dispatcher to handle IsExpanded asynchronously and see how it behaves. This requires that you don't use the expanders default action:
In the arrow button click handler, skip default handling and insert this (IsExpanded is your bound viewmodel property here):
Dispatcher.BeginInvoke(DispatcherPriority.Normal, new Action(
() => { this.IsExpanded = true; } ));
I apologize for the crappy title, I wasn't quite sure how to summarize what I'm trying to do.
My scenario:
I am refactoring an existing WinForms application to WPF and MVVM. I'm currently working on a module that provides search functionality for a database comprised of many different tables such as Contact, User, Case, Product, etc. In code-behind there are classes which provide an Object for each. I have written wrapper classes for each of the searchable table Objects that expose only the properties a user would want/need to see in the search results for each type of Object, for binding to a DataGrid.
Once these search results exist, they need to be displayed in a combination of Tab Controls and Data Grids, like so:
Because of some use cases, I need to be able to create an individual display Tab+DataGrid for the results of every single search that is performed. I cannot have a single tab for each type of search that is shown/hidden as needed.
I'm not sure how to proceed from where I currently am to the goal pictured and described above. Thanks for any help anyone can provide.
Not sure I entirely understand your question, but it looks to me that it might be a candidate for datatemplateselector.
Basically, you use an ItemsControl bound to your result collection and then - using a datatemplateselector - you swap in the appropriate template to display the item based upon a code inspection.
That will let you present all the results in a single list.
If you want to display your results in a tabs, I would present a collection of each result type in your viewmodel. So you have a Users collection and a seperate Products collection. Then you can bind individual data grids to each template.
If you want to then hide the tabs when no results are present, add a data trigger using the expression.interactivity namespace to trigger the visibility of each tab page based on its respective collection count.
One more thing, if you want to create tab items dynamically, i.e. One tab for each search - the tab control has an ItemSource property. If you group each search result into an object an expose an observable collection of that object, you can bind that to your tab control and have it create tab items for each search result. Just make that object contain a collection of actual results and you should be able to create a itemscontrol as mentioned here already.
Sorry if this appears a bit of a mind dump, but like I said - not sure if I entirely get the question :)
Rather then chuck a load of code snippets in, there a plenty of samples just a google away if anything sounds helpful.
This is a getting started question about how to create a reusable wpf slideshow control:
that displays a sequence of any visualizable elements e.g. a series of Image controls or a series of UserControls (should I target ContentControl, or is there a broader type that encompasses more visualizables/controls?)
the control should be able to accept an IList of some kind, which would be the elements/slides to present
the control should expose an Interval property that determines the duration of each slide, but i dont even know the basics of how to get started with that in terms of offering that property to be configured in xaml?
and what should the container be, if any, for the individual slides/controls that are passed in?
To start with, you should probably create a UserControl which contains an Image control, and perhaps Next/Previous Buttons, and anything else you may need. These would all be laid out as normal using a variety of panels, you could probably style most of it with just a Grid.
After that, your UserControl will implement the ImageSource (your IList, or IEnumerable of images), and your interval as dependency properties. These are then settable in XAML.
You would then write the logic which loads the next image and sets it as the Image's Source property, this could happen in the change event for the ImageSource property. You can then get as advanced as you wish with Image preloading/caching etc.
I've just delved into WPF myself for a "Slideshow" like project where I'm showing customer order numbers on screen for a period of time before showing the next, and using Effect/Transitions/Storyboards to move to the next frame. I found a good article on CodeProject
I used a Grid with 2 rows:
Contains my "Changing area".
Contains static information (logo, controls etc).
Rememeber to set "cliptobounds = true" on your changing area if you use any sort of transforms on it. (I know you said you aren't using transitions initially, but once people see it, they'll be asking).
Dependency properties are also easily built in C# if you just type propdp and hit tab.
I would like to store and display a list of complex items. Each (graphic) item has to display an image, a list of color chips, a label and an index (a letter). User would also be able to zoom within each item, to show details of the image (on mousewheel),
Items would be presented in a vertical list, scrollable and resizable.
Language is C#, .net2.0, or 3.5 only if necessary.
I'm think about using custom UserControls for items (each one composed of a PictureBox, 2 Labels and a custom UserControl to display color chips).
For the list, I really don't know what to choose between a ListBox, a ListView, or a DataGridView, or another one I don't know yet.
I basically would go for a ListBox for its simplicity. Could you help me clarifying the advantages of using other lists?
If you expect to have a large number of these items, I strongly recommend that you do NOT make each one a UserControl. This is doubly important if you intend to localize and globalize the application at some point. The creation of these items will hinder performance.
Instead, take a lighter weight approach so that the items don't have the overhead of a full-blown control. Assuming that each item will be rectangular, you could easily create a UserControl for painting them, including a scrollbar to scroll.
in your case a custom (third party) list control seems to be the way to go. ListBox, a ListView or DataGridView are rather too limited given your requirements.
Regards,
tamberg
Thanks for your answers. It's very helpful to me.
I'm sorry I didn't mention that the list and its items have to manage drag-dropping with other controls. Then, I suppose that items have to be separate controls. Also, list would be dynamic and would not contain more than 30 items.
So, if I understand your advices, I should create a custom UserControl for the list and one for the item.