如何在C#Windows窗体中创建选项表单?

时间:2013-08-10 22:16:13

标签: c# forms treeview options

http://i.stack.imgur.com/v58ov.png

见上图。这是Visual Studio选项表单的截图。

左侧基本上是TreeView。右侧是各种控件,可以更改程序选项。 选择TreeView中的节点后,右侧会更改,显示不同的选项。

你如何编程这样的东西?右侧是否只有50个重叠的面板,选择节点只会改变哪个面板可见?如果是这种情况,您将如何管理?这将是设计师的一个烂摊子。

3 个答案:

答案 0 :(得分:6)

不,你不会制作50个重叠的面板。只需创建多个用户控件,例如,链接节点标记上的类型。您可以使用Activator来创建控件。 创建1个树视图和1个面板:( PSEUDO CODE)

// create nodes:
TreeNode item = new TreeNode();

item.Tag = typeof(UserControl1);

TreeView.Nodes.Add( item );


// field currentControl
UserControl _currentControl;


// on selection:
TreeViewItem item = (TreeViewItem)sender;

if(_currentControl != null)
{
   _currentControl.Controls.Remove(_currentControl);
   _currentControl.Dispose();
}

// if no type is bound to the node, just leave the panel empty
if (item.Tag == null)
  return;

_currentControl = (UserControl)Activator.Create((Type)item.Tag);
Panel1.Controls.Add(_currentControl);

接下来的问题是,“我想在控件中调用save方法或RequestClose方法”。为此,您应该在控件上实现一个接口,当您切换节点时,只需尝试将_currentusercontrol转换为IRequestClose接口并调用,例如,bool RequestClose();方法

 // on selection:
 TreeViewItem item = (TreeViewItem)sender;

 if(_currentControl != null)
 {
    // if the _currentControl supports the IRequestClose interface:
    if(_currentControl is IRequestClose)
        // cast the _currentControl to IRequestCode and call the RequestClose method.
        if(!((IRequestClose)_currentControl).RequestClose())
             // now the usercontrol decides whether the control is closed/disposed or not.
             return;

    _currentControl.Controls.Remove(_currentControl);
    _currentControl.Dispose();
 }

 if (item.Tag == null)
   return;

_currentControl = (UserControl)Activator.Create(item.Tag);
Panel1.Controls.Add(_currentControl);

但这将是下一步。

答案 1 :(得分:0)

对我而言,其常见的设计是左侧的经典树视图和右侧的“内容区”。当用户在树视图中选择某些内容时,您将在内容区域中加载相关视图。在有很多不同的方法来实现这些东西之后,例如,自动生成基于对象列表的树视图,该对象列表包含要实例化的视图类型,并创建一个在选择项目时创建相关视图时调用的通用实例化器,无论如何,背景仍然是一样的。要恢复,请查看树视图,然后根据所选项目在内容区域中创建视图。 (我在工作中看过几个这样的画面,大部分时间都是这样的)

答案 2 :(得分:0)

在检查了几个选项之后,我的方法是继承TabControl组件,使得控件的页面可以用作分页面板,并添加功能,以便选项卡不会在运行时显示。然后,通过创建一个名为Pages的属性,该属性依赖于TabPages,我可以以语义正确的方式引用每个页面,这样可以将每个页面作为Pages集合的一部分进行管理,并且还可以通过文档资源管理器进行分层管理。

该代码还隐藏了与常规TabControl相关的设计时属性,但这在分页面板中无关紧要。如果有人有兴趣,下面是代码。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.ComponentModel;
using System.Drawing;

namespace MyCustomControls
{
    public class PagedPanel : TabControl
    {
        //------------------------------------------------------------------------------------------------
        public PagedPanel()
        {
            base.Multiline = true;
            base.Appearance = TabAppearance.Buttons;
            base.ItemSize = new Size(0, 1);
            base.SizeMode = TabSizeMode.Fixed;
            base.TabStop = false;
        }
        //------------------------------------------------------------------------------------------------
        protected override void WndProc(ref Message m)
        {
            // Hide tabs by trapping the TCM_ADJUSTRECT message
            if (m.Msg == 0x1328 && !DesignMode) m.Result = (IntPtr)1;
            else base.WndProc(ref m);
        }
        //------------------------------------------------------------------------------------------------
        protected override void OnKeyDown(KeyEventArgs ke)
        {
            // Block Ctrl+Tab and Ctrl+Shift+Tab hotkeys
            if (ke.Control && ke.KeyCode == Keys.Tab)
                return;
            base.OnKeyDown(ke);
        }
        //------------------------------------------------------------------------------------------------
        [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [DefaultValue(true)]
        public new bool Multiline
        {
            get { return base.Multiline; }
            set { base.Multiline = value; Invalidate(); }
        }
        //------------------------------------------------------------------------------------------------
        [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)
        , DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [DefaultValue(TabAppearance.Buttons)]
        public new TabAppearance Appearance
        {
            get { return base.Appearance; }
            set { base.Appearance = value; Invalidate(); }
        }
        //------------------------------------------------------------------------------------------------
        [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)
        , DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [DefaultValue(typeof(Size), "0, 1")]
        public new Size ItemSize
        {
            get { return base.ItemSize; }
            set { base.ItemSize = value; Invalidate(); }
        }
        //------------------------------------------------------------------------------------------------
        [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)
        , DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [DefaultValue(TabSizeMode.Fixed)]
        public new TabSizeMode SizeMode
        {
            get { return base.SizeMode; }
            set { base.SizeMode = value; Invalidate(); }
        }
        //------------------------------------------------------------------------------------------------
        [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)
        , DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        public new TabPageCollection TabPages
        {
            get { return base.TabPages; }
        }
        //------------------------------------------------------------------------------------------------
        [EditorBrowsable(EditorBrowsableState.Never), Browsable(false)]
        [DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
        [DefaultValue(false)]
        public new bool TabStop
        {
            get { return base.TabStop; }
            set { base.TabStop = value; Invalidate(); }
        }
        //------------------------------------------------------------------------------------------------
        public TabPageCollection Pages
        {
            get { return base.TabPages; }
        }
        //------------------------------------------------------------------------------------------------
    }
}

树视图将处理按键或索引调用每个选项卡,这是一项相对简单的任务。我这样做是通过命名树中的节点,例如" tvn",然后在PagedPanel中命名页面相同但前缀为#34; pg"。所以在树视图的AfterSelect事件中,我需要的只是当前节点的名称,我知道要显示的页面。