ordered list of user controls (with addition and deletion) - c#

Some context
I am creating an application which allows users create basic shelving arrangements, I wish to create an interface which represents shelving blocks(one set of shelves) next to each other in order (left to right) and allows users to edit their details.
Each block will have a series of details such as its order,a name, a width, a height and a number of shelves.
Requirements
I want the interface to have a horizontal scrolling list of (max 20) user controls. Each user control will represent the details of a block, with a basic form for these details to be edited.
The user should be able to press a button in the user control which deletes it and reorders the other blocks and also add blocks to the end of the list.
My Question
How do I maintain an ordered list of these 'shelf block' user controls, and have the form handle the pressing of the deletion button in any of the controls which causes it to be deleted and the list to be reordered? Any help would be great.
Screenshot
I am just starting to program the interface so I can only provide a quick mock up of what I want the interface to look like:
as basic as it is I hope it gives you some idea of what I'm looking for.

You can use a BindingList to store your blocks. A BindingList will notify the UI control (e.g. a ListBox) that data has been changed such as a block being deleted. The UI will then reflect this by removing the block from the ListBox. If you're familiar with WPF/Silverlight databinding this is similar to, but not quite the same as, an ObservableCollection list (if you're targetting .NET 4, I believe you may be able to use ObserverableCollections in a WinForm without much trouble but someone else may be able to clarify that).
Alternatively, you can use a BindingSource instead of directly using a BindingList.

How about putting a hidden grid control on your form.
Then you just add/ remove rows to the grid with the desired data
and everything is kept very orderly. One advantage here is that
for debugging purposes you can always make the grid visible to see
all the data quickly.

Related

Best way to add "dynamic" controls?

My program will prompt the user for a number, i.e. 25. The program will then start the "main form" with 25 controls (textbox). The 25 (or whatever number) of textboxes (or whatever control) will need to be formatted evenly. I will also need to be able to retrieve the text (or another property if I use another control) in order, from left to right and up to down. What is the best method of approaching this?
Using WPF MVVM. In a .XAML file, create a DataTemplate with the DataType of a ViewModel that will provide the binding for your TextBoxs, lets call this the TextboxViewModel. Then using a ItemsControl element with an ItemsSource of TextboxViewModel. You'll be able to instantiate as many TextBoxs as you want and be able to get the result by browsing through your list of TextboxViewModel.
Supposing you are using Windows Forms here.
Dynamically create the X controls and add them to the Controls collection of your form. To ease the access to them you can store their reference in a List and set some event handlers too, depending on your needs. You just need to calculate their positions while you add them.
If WinForms, this is exactly what the FlowLayoutPanel is for. Just add the controls to it and they will arrange themselves automatically, wrapping down to the next row as needed. As Mihai already suggested, you could also keep reference to those controls in a List.
Another option would be to use a TableLayoutPanel. It's a little more difficult to learn and use, but is much more flexible and powerful.

Dynamically creating Tab+DataGrid for binding with multiple different classes?

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.

Conditionally validate Dynamically generated Controls in Silverlight

I am having a form with different type of controls like Text Box, Drop downs, Check box, Radio buttons etc. All these controls are loaded dynamically from database at run time.
I want to perform validation on Text box on conditional basis. For example, If we have selected any value in drop down, then you must have to fill details in Text box. Otherwise text box details are not required.
I am open to use database to perform this task and I am using MVVM pattern in my project.
Any help on this is highly appreciated.
Thanks.
(I started this as a comment, but it ended up being too long).
In theory you have access to all these controls and their values in your ViewModel.
Without knowing the specifics of your program, it's difficult to suggest anything useful, but in essence you need to expose some more properties from your ViewModel (probably boolean) which will be calculated based on the values in your controls. Then you need to bind IsEnabled properties on your controls to these new properties.
Sounds simple, but I think you have some architectural problems which will make it difficult to implement what I suggested above. In order for this to work and automatically update your controls whenever other controls' content change, your ViewModel needs to implement INotifyPropertyChanged and raise PropertyChanged event every time you update one of those boolean properties.
I think what you're trying to do could be achieved with ItemsControl and DataTemplates (and maybe DataTemplateSelectors). This will allow you to store "data" in your ViewModel (say List or something more specific) without referencing the actual Controls and the relevant DataTemplates will add the right controls for different data types you have in your ViewModel.

User sortable list control

I need to give to a windows form user (C# 4.0 application) a way to act on a control showing a list containing several items. What is needed is to give to the user a way to select an item and then to move it upside or downside because changing the order. A possible solution is in the following image that shows a possible implementation using a couple of buttons (labeled + and -) to change a sort key value for each element then giving the reorder responsibility to an override of the alphabetical sort provided by a ListBox control. The change must persists until form disposal
I am wondering if there is a better or simpler way to get the same result; maybe there is some control featuring capabilities that I am unaware of. Thanks
There's no builtin control for this. The solution you suggest can easily be implemented using the Remove and Insert methods for the ListBox.Items collection.
Another solution could be to allow the user to drag & drop the items. Look at CodeCaster's link in the comments to your question.

Trying to figure out how to allow a user to edit a collection with a DataGrid

I'm working on a plug-in for a 3D modeling program to assist in architectural design. I have a Building class which needs to contain a collection of Floors.
My Floor class has properties such as Elevation, Height, ProgramType (residential, retail, etc), and ID. Each building has a FloorList property which is the collection of all the Floors contained by the Building. The properties of a Building are generally viewed through a property grid control and I was planning on using a custom UITypeEditor to allow the user to edit the FloorList collection.
I'm trying to figure out the best way to create this FloorList collection class so that creating the UITypeEditor is as easy as possible, and I can take advantage of any existing collection editing ability's in the .NET controls. For the editor I was thinking I'd use a DataGrid view to show all the floors in the collection something like the table below.
Height Elevation ProgramType ID
15' 70' Residential 23423
15' 55' Residential 42342
15' 40' Residential 98723
20' 20' Retail 23454
20' 0' Retail 98723
The user should be able to edit the height of the floor through the DataGrid, but the elevation of a floor would be derived from the sum of the floor heights below it. The program type should either be a text box or a drop down, and the ID is a read only value shown for information only.
The interface should also allow the user to edit the members of the collection such as adding one or more floors, removing one or more floors, or changing to order of the floors.
The DataGrid control has some built in functionality for allowing a user to add and delete rows, but is there built in functionality to allow a user to reorder the rows?
The only times I've ever used a DataGrid has been to show a DataTable. Is there a straight forward way to use a DataGrid control to allow a user to see and edit properties of objects in a collection? What about being able to add and remove objects from that collection by adding or removing rows from the DataGrid?
One caveat to this problem I have is I can't just edit the collection items directly, as changes to one item will affect another. For example if I remove a floor I'll need to move down (change the elevation of) any floors above the removed floor. Likewise if I increase the height of a floor I'll need to move any floors above the taller floor up. So any changes to the collection or items in the collection will need to be done through the collection itself rather then directly at the item.
So again I was thinking my FloorList collection would implement IEnumerable so that other methods could itterate over all the floors in a building. But any actual manipulation of the collection or objects in the collection would be done through Methods of the collection such as....
FloorList.AddFloor(Floor floorToAdd);
FloorList.RemoveFloor(Floor floorToRemove);
FloorList.MoveFloor(Floor floorToMove,int newPosition);
FloorList.ChangeFloorHeight(Floor floor);
etc..etc...etc..
Sorry for the long question, especially with out any sample code. But right now I don't really have any code written as I'm for once trying to plan out my work rather then jumping right into the code.
Update
I've been reading some examples and it looks like the DataGrid will show properties of objects in an IList. So now I'm thinking it makes more sense to implement a List, but set up the overridden methods to handle changing the floor elevations. If I'm ultimately going to be binding this list to a DataGrid control would it be better to base the FloorList collection of BindingList or IBindingList instead?
Update
I've done some more reading and decided to completely reword my question. The new version is here.
To answer your first question: In your business layer I would have Create, Add, Edit, Delete (and so on) methods that handle all your custom logic (just have it pass in your models to these methods). Then call those methods through the OnEditing, OnUpdating, etc. events from the DataGrid.
To answer your second question, BindingList will give you a built in OnChange event whereas the List will not. If this is being used in a Windows Form app, BindingList will come in handy. But using that event in a Web app can get kinda hairy. It depends on how you want to implement the updating logic in your business layer.

Categories