Results 1 to 6 of 6

Thread: [Ideas wanted] Options view control - child options

  1. #1

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    [Ideas wanted] Options view control - child options

    Hi,

    I am in need of a form that shows various options, exactly like the Options in Visual Studio. Since there are so many options I too want them categorized, with a TreeView to the left taking care of showing the right category.

    The usual 'easy' approach here would be to just place a TreeView control on the form, add some nodes, and give those nodes a tag or key that corresponds to a panel or UserControl with the options for that category.
    Since there will be a lot of options however, this is not really feasible design-wise; the form would be cluttered with possibly 50 panels, all of which I would need to select and bring to front from time to time to add controls to them that represent the options.


    So I decided to create a custom control that does exactly that. The control is very similar to my Wizard usercontrol, users can add OptionsPanels at design time, which inherit Panel and simply represent one panel of options. When they do, the panel is added to a container panel, and at the same time a TreeNode is added to a TreeView. The control uses a custom ControlDesigner to handle design-time clicks in the Treeview, selecting a different node would select and bring to front the corresponding panel, allowing the user to add the controls he wants.

    Due to the design time support the problem of having 50 panels is no longer present, only one panel will be visible at a time and selecting the right panel is as simple as selecting the corresponding TreeNode, just as during run-time.



    Anyway, I got all this working, but only for a single 'level' of categories. As you can see in the Visual Studio options, there can be multiple levels of categories. For example, the Environment node has a bunch of children, where each child represents one 'options panel'. There can even be deeper nesting, see the Text Editor node for example.


    I am having trouble designing this feature and would appreciate some help or ideas.



    Let me begin by drawing out the basics of how my control works so far.

    The main control is an OptionsView control, which contains a SplitContainer with a TreeView to the left and a OptionsPanelContainer to the right. The OptionsPanelContainer is merely a Panel to which only OptionsPanel controls can be added, and which raises events when this happens, as well as when OptionsPanels are removed from it.
    An OptionsPanel also inherits Panel, and these are the actual panels the users will see in the control, one for each option category.
    For now, each OptionsPanel has exactly one corresponding TreeNode (and vice versa). In the Visual Studio options, each 'parent' category usually has a 'General' node as the first child, and the parent and this General node show the same option panel, but I am ignoring that for the moment.

    The OptionsView control has a property Panels that returns the ControlCollection (Controls property) of the OptionsPanelContainer (in other words: it returns a collection of OptionsPanels that are in this container panel).
    vb.net Code:
    1. <Editor(GetType(Designers.OptionsPanelCollectionEditor), GetType(UITypeEditor))> _
    2.     <DesignerSerializationVisibility(DesignerSerializationVisibility.Content)> _
    3.     Public ReadOnly Property Panels As Control.ControlCollection
    4.         Get
    5.             Return Me.PanelContainer.Controls
    6.         End Get
    7.     End Property

    A custom CollectionEditor for this property takes care of the designer: even though the property type is ControlCollection, the CollectionEditor knows it should create instances of the OptionsPanel control instead of just Controls.

    When it does this, a corresponding TreeNode is also created and its Tag property is set to the OptionsPanel. Vice versa, the Node property of the OptionsPanel is set to the node. Hence the node and panel both know their corresponding object.
    vb.net Code:
    1. Public Class OptionsPanelCollectionEditor
    2.         Inherits System.ComponentModel.Design.CollectionEditor
    3.  
    4.         Public Sub New(type As Type)
    5.             MyBase.New(type)
    6.         End Sub
    7.  
    8.         Protected Overrides Function CreateCollectionItemType() As System.Type
    9.             Return GetType(OptionsPanel)
    10.         End Function
    11.  
    12.         Protected Overrides Function CreateInstance(ByVal itemType As System.Type) As Object
    13.             If itemType Is GetType(OptionsPanel) Then
    14.                 ' Use the IDesignerHost service to create a new component
    15.                 ' This way it's editable during design-time
    16.                 Dim designerHost = DirectCast(Me.GetService(GetType(IDesignerHost)), IDesignerHost)
    17.                 Dim panel = DirectCast(designerHost.CreateComponent(GetType(OptionsPanel)), OptionsPanel)
    18.                 Dim view = DirectCast(Me.Context.Instance, OptionsView)
    19.  
    20.                 ' Also set some properties
    21.                 panel.Owner = view
    22.                 panel.Dock = DockStyle.Fill
    23.  
    24.                 Dim node As New TreeNode(panel.Name)
    25.                 node.Tag = panel
    26.                 panel.SetNode(node)
    27.  
    28.                 Return panel
    29.             End If
    30.  
    31.             Return MyBase.CreateInstance(itemType)
    32.         End Function
    33.     End Class

    Finally, when an OptionsPanel is added to the OptionsPanelContainer, it raises an event and its TreeNode is added to the TreeView. The same goes for removing. When a TreeNode is selected, its Panel is set as the SelectedPanel. Setting the SelectedPanel merely hides all panels except the selected one:
    vb.net Code:
    1. Private Sub container_PanelAdded(sender As System.Object, e As OptionsViewLibrary.OptionsPanelContainer.OptionsPanelEventArgs) Handles container.PanelAdded
    2.         Me.TreeView.Nodes.Add(e.Panel.Node)
    3.     End Sub
    4.  
    5.     Private Sub container_PanelRemoved(sender As System.Object, e As OptionsViewLibrary.OptionsPanelContainer.OptionsPanelEventArgs) Handles container.PanelRemoved
    6.         Me.TreeView.Nodes.Remove(e.Panel.Node)
    7.     End Sub
    8.  
    9.     Private Sub tvw_AfterSelect(sender As System.Object, e As System.Windows.Forms.TreeViewEventArgs) Handles tvw.AfterSelect
    10.         If e.Node IsNot Nothing Then
    11.             Dim panel = TryCast(e.Node.Tag, OptionsPanel)
    12.             If panel IsNot Nothing Then
    13.                 Me.SelectedPanel = panel
    14.             End If
    15.         End If
    16.     End Sub


    So far so good, this all works fine. I can add Panels via the designer and when I do a new TreeNode appears in the TreeView. I can select this node and the panel becomes visible (comes to the front).


    Now, I am a little stuck. How do I implement child option panels? And more importantly: how do I let the user add child panels?

    The most logical choice I think is to let each OptionsPanel have a property (ChildPanels or something) that returns the child OptionsPanels for that panel. Once the user selects an OptionsPanel then, he can look in the property grid to find its ChildPanels property and add child panels to that.

    There is a problem though: what would this property return? It must return a ControlCollection of some container (this is, I think, a requirement for the designer features to work, otherwise panels are not added to the Form.Designer.vb file).
    But there is no container. I cannot add them to the OptionsPanel itself, that would make no sense because the parent OptionsPanel has its own set of controls (the options itself...), there cannot be another (fully docked) Panel on top of those obviously.
    The container of the main OptionsView then? That is not an option either, its Controls collection holds ALL OptionsPanels, not just the children of the selected panel. I cannot 'select' only the right panels either, that would require me to return a new instance of ControlCollection, it would be impossible to return the actual ControlsCollection that holds merely a small selection of its controls.



    I realize this post might be hard to understand, but if you have any idea at all just let me know, perhaps I can work with it.
    Thanks!

  2. #2

    Re: [Ideas wanted] Options view control - child options

    So you want the user to be able to add additional panels that are childs of the current panel? I've re-read the entire post a few times and I still haven't come to a conclusion about what it is you're exactly trying to accomplish.

  3. #3

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: [Ideas wanted] Options view control - child options

    Well, yes and no. The additional panels will not be children of the current panel, at least not in .NET terms. All panels should be parented by the one OptionsPanelContainer control, which is just a panel on the right side of a split container. However, for each panel there is a corresponding TreeNode in the treeview, and this TreeNode can be parent by other TreeNodes to create a hierarchy of options, exactly like the Visual Studio options screen (and many more like it).

    So the user might create a hierarchy like this
    Code:
    [-] General Options
     --- Loading & Saving
     --- [+] Fonts 
     --- [-] Colors
           --- Abc
           --- Def
          
    [-] Text Editor
     --- VB.NET
     --- C#.NET
     --- Javascript
    
    [-] Misc
     --- License
    Each node corresponds to one Panel, and selecting one node brings that panel to the front.


    There might seem to be two options for adding the nodes:
    - Add the nodes, and then add the corresponding panel
    - Add the Panel, and then add the corresponding node

    Option 1 would be ideal, but is not possible as far as I know due to design-time issues. For the panels to be actually added during design-time as well as remembered (serialized in the Designer file) they have to be added to the ControlCollection of the container. So, option 2 is the only way. Once a panel is added, I add the corresponding TreeNode to the TreeView.

    The problem now is adding child nodes. I can only add 'parent' nodes/panels at the moment because only the main usercontrol has a Panels property (the one that returns the ControlCollection of the container) to which panels can be added.
    This leaves no possibility to add child panels.

    Ideally, each OptionsPanel would have another Panels property, just like a TreeNode has another Nodes property that returns the child nodes. But that seems impossible because the OptionsPanel.Panels property must still return the ControlCollection of the container (design-time issue) but that is impossible because it contains all other panels as well, not just the child panels.


    So what I'm looking for is another clever way for the user to add child panels. As far as I can see, a Panels property on each OptionsPanel is impossible... I fear this is going to be harder than I first thought



    The only thing I can think of right now, and I have no idea if that would work, is to let the OptionsPanel have a ParentNode property. When the user is adding panels, he gets a collection editor (just like any other collection editor during design-time) with a list of panels to the left and a propertygrid to the right. The user could then use that property grid to select a TreeNode to be used as the parent node. It's not very user friendly but it might work...

  4. #4

    Thread Starter
    PowerPoster
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,070

    Re: [Ideas wanted] Options view control - child options

    Ok, after quite some work* that seems to work ok. I can select parent nodes for each panel and this way the user can build the hierarchy. It's not ideal though, so if anyone has a better idea, please...

    I did have another idea, to create my own collection editor form for the Panels property and not use the built in collection editor, but I haven't really thought about that yet.



    *It seems you cannot edit nor select properties of type TreeNode in a property grid. I had to write my own UITypeEditor for the ParentNode property that creates a ListBox, fills it with the TreeNodes currently in the TreeView and displays that.

  5. #5
    PowerPoster JuggaloBrotha's Avatar
    Join Date
    Sep 2005
    Location
    Lansing, MI; USA
    Posts
    4,286

    Re: [Ideas wanted] Options view control - child options

    This actually sounds like it would be a really neat control to have, would you mind sending it my way when you've got it (mostly) done?
    Currently using VS 2015 Enterprise on Win10 Enterprise x64.

    CodeBank: All ThreadsColors ComboBoxFading & Gradient FormMoveItemListBox/MoveItemListViewMultilineListBoxMenuButtonToolStripCheckBoxStart with Windows

  6. #6

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width