I'm interested in what is the best way to implement the removal of related set of UI elements.
This is what I'm working on: I have a Grid embedded within a verticle Scrollviewer. The user can add multiple Listboxes to this Grid during runtime via a button click. Each ListBox, when added, will also result in the addition of the correct number of Grid Rowdefinitions and a Gridsplitter to allow the resizing of each Listbox. This parts works fine.
The trick is this -- the user also has the option of closing a Listbox. When they do this, I will need to remove the corresponding Rowdefinitions and Gridsplitter that "belongs" to the closing Listbox.
Via iteration through Grid.Children and Grid.Rowdefinitions, I could somewhat easily figure out which Rowdefinitions and Gridsplitters to remove. But I'm wondering if there is a better way to handle this. Perhaps by grouping these elements together in a collection and simply removing this collection in one fell swoop? No idea how to do this, though.
Any ideas or suggestions are greatly appreciated!
I'm not aware of an obvious or simple way to associate them within the visual/logical tree, but you could certainly use an associative array (Dictionary<T, U>) that's keyed off of the element you're removing with the contents as the other items that need to be removed.
I think this is essentially what you described.
Anything more clever wouldn't be worth the additional complexity, I think, unless you had a specific need for it. :)
Related
The best way to show what I need is showing an image:
What is the easiest way to implement this kind of "nested ListView" - each Item can be expanded and has subitems. I want the hierarchy only to show on the first column as shown when any other solution can be accepted.
There are couple of ways to do it. I consider that you are good in WPF and easily check code and take idea from it because it is not easy to give code of your requirement here.
You must need to user Expander for expand and collapse functionality for the detail sections as per you image.
I am sharing some the links from where you can easily get what you want. It is not exact code which you can copy but it will give you basic structure of what you want.
Listview and Expander
Sample-1
Expander and DataGrid
Sample-1
Sample-2
You will enjoy working on this one.
I've written a custom panel which displays its children docked either vertically or horizontally, separated by moving splitters in between. Since the Grid panel offers much of this functionality out-of-the-box, I just inherited from it.
To create the layout, upon Loaded is fired I do the following:
1) Read how many children it has and create the appropiate number of rows/colums.
2) Position every existing children in the corresponding row/colum.
3) Create, position and add a GridSplitter for every child.
This approach looks and works fine, but it opens the door to a lot of problems:
Since it's added a GridSplitter for each child, there are twice the number of expected children. If someone added 3 elements to it, Children.Count would return 6.
User could insert/remove things at the wrong place.
It just throws an exception when this Grid is used as the ItemsPanel for an ItemsControl, since in this case WPF (not Silverlight) does not allow direct children manipulation.
These 3 cases are the ones I've already tested, but I'm pretty sure a lot more would arise depending on what the user does with it.
As it turns out, this class must be regarded as 'implementation details', so the real question is, what control should I put in front of the user?
It sounds like it should be a Panel, but I can't control the Children property since it's not virtual, and there's also the ItemsControl which I think could be a good candidate, but I really don't know.
I'd much appreciate any kind of advice or some directions to do this the right way.
Thanks in advance.
You see using just grid you leave yourself with an imperative way of adding items only. As in
myCustomGrid1.AddMyItem(***), Grids simply don't have ItemsSource property. ItemsControls do - so if you need support for declarative items sources i.e. myControl.ItemsSource = {Binding ...} you're going to derive your control from ItemsControl. This is not a two liner - making your ItemsPanel Children writable is a big challange - there's no simple way of doing that.
This is all about a small thing overlooked during the Grid's design - splitters shouldn't have been added to Children collection, as Children are visulaizations of your BOs while spliiters are just formatting elements.
Here's what I would do.
Forget about ItemsSource & items altogether - it's aint worht the hassle. The only way to add/remove items to your control will be AddResiazableItem/RemoveResizbleItem. Calls will add items and splitter (for the middle items), extend the number of rows/cols of your grid depeneding on its orientation, set Grid.Row/Grid.Column attached properties for your visual children. You can keep your actual objects internally to support Orientation change.
If at any stage you'll want to bind your control to IEnumerable source - just create an attached behavior, which will iterate through the items and call AddResiazableItem within a loop.
Cheers.
P.S. To moderators - the editor seems to get broken, lads. I cant see the second item.
P.S.S. Got it fixed after a few tries.
Here's my scenario. I want to be able to drag and drop elements around in a items collection, and have other elements make way when an item is moved into place... I also want this to be MVVM friendly.
From a high level view it seems to me you should be able to just attach some sort of Interactivity behavior to the items collection that simply gets the layout size of the dragged item, and shuffles elements based on that new layout data, but I'm at a total loss on how to implement something like this.
Other features to consider would be
Auto-scroll on scrollviewer edge during drag operations
Inserted objects may be of variable sizes
It seems to me I'll need to use a FluidMoveBehavior
Look at the project at http://code.google.com/p/gong-wpf-dragdrop/. It can help you solve your problem. The solution is MVVM based on attaching drag&drop behaviours to UI elements and customizing the way how DragXXX events are handled.
I am new to WPF environment and I am experiencing some problems like if there are alots of things how do we manage them.for example I have three borders each of same size same location and they contains controls like textboxes etc etc we construct them sequentially but when it comes to edit we get in trouble modifying the border that is at bottom.
So in short how do we manage many controls on single page so that it remains easy to edit
Not sure I completely understand your concerns, but here are several point that make editing WPF UI pretty easy:
Correct usage of layout panels. If you will use approach with absolute positions for each control then it might become a nightmare to move or resize some of your controls. Correct layout (and panels such as DockPanel/StackPanel/etc) might help you a lot.
Incapsulating repeatable parts. WPF has a lot of feature to avoid repeating UI code. I'm talking mostly about Styles and Control templates at the moment. If you have your borders repeating through the entire window, maybe you should think on extracting this border as a ControlTemplate for ContentControl for example?
but I've found that encapsulating controls such as borders, textboxes etc in User Controls helps to keep things well managed (not to mention helps reduce code), similarly using a Resource Dictionary to store styles/animations is useful for very big projects (remember though that the local resources will take precedence when applied so remove them if they not in use)
furthermore, using Layout Panels such as Stacks,Grids and Dockpanels allows you to collapse User Controls when not needed or otherwise (also I've found that for some reason, Grids allow controls to overlap (when items are not correctly ordered in Grid Rows and Columns) which can lead to some elements not being seen in design.
Plan your layout properly and think through which Panels would be best for them, having to go back much later and change can be annoying (though admittedly it happens).
Also remember to use partial classes to properly structure your stuff, having to read through 1000+ lines of code to find something can be a nightmare.
How can I add column headers to a Silerlight ItemsControl? I need a fast way to display a List of items that contains also some header info.
This may seem like a simplistic question but why not use the DataGrid in readonly mode?
The downside with data grid is it doesn't use a virtualised ItemsControl so performance may suffer if you are trying to list hundreds of items with many columns.
There's nothing built into the ItemsControl itself, but there's nothing to stop you from making a custom control that has that kind of functionality. It's a little work up front for the ability to reuse it later if it's a piece of UI you need frequently.
Adding too much functionality to it might be overkill though; if you need column sorting or automatic column/header generation, you may find that a DataGrid (as Anthony pointed out already) would be a faster way of getting a lot of functionality for free.