官方QQ群:127876820【C#编程技术-全国站--未满人】

项目中如何明确用户界面需求的想法分享

在应用程序开发中,需求不清晰从而导致需求变更是一个让所有人深恶痛绝的事情,用户界面也是其中很重要的部分。之所以用户的需求不清晰是因为在很多时候,用户的脑海中往往只会构思和想象用户界面的一部分,他只能告诉你他想要的软件大概是个什么样子,有哪些功能和操作;你们也许会在纸上或者通过绘图工具绘制一些用户界面,这也不够准确直观;而让用户自己使用VisualStudio设计他想要的界面更是不现实的。所以,我们是不是可以提供一个简单的界面设计器,让用户自己设计他的一部分界面,从而使得他的需求更明确些呢?

  Microsoft Expression Blend就是这样的一个软件,但是Blend还是太专业复杂了些,用户肯定不愿意去学习使用这样的软件;而我们自己做一个界面设计器也代价太大,使用第三方开发的软件也需要购买成本和学习成本。所以,我想我们是不是可以先做好一个大概的界面原型,然后让用户自己设置更改这个界面原型?

我设想的流程是这样的:

  1.  开发人员和客户先讨论界面大概做成什么样子。

  2.  开发人员做出一个界面的原型,就是一个From。

  3.  客户将Form跑起来,并能够自定义该Form,能够给Form及Form上的元素加注释。

  4.  客户将自定义的Form保存,开发人员拿到结果后再做一个原型…

  关于界面原型的一些初步构想:

  1、 只做一个纯粹的界面,界面上不需要加事件处理函数等,除非会弹出另外一个需要和客户确认的Dialog/Form。

  2、 在希望用户自定义的地方(一般而言是Form或者某个控件)添加ContextMenu或者其它可以定制控件的能力,但是添加的设计功能不应该影响用户对于界面的直观感受,所以直接暴露在用户眼中的部分越少越好

  3、 应当给用户设置每一个控件注释的能力,注释中包含开发人员的解释以及客户的解释,比如说这个按钮点击以后会发生什么事,而客户对于无法设置的地方也可以加上他自己的想法。

  关于如何保存用户对界面的修改:我们可以把Form对象序列化成源代码,就像在VisualStudio的设计器中设计Form那样。至于如何将一个Form序列化成源代码,请参照从Component对象到CodeDom——舞动你的Code系列(1)

  开发人员拿到源代码后,根据客户的改动以及注释再做一个更接近用户想法的原型,可以再给客户自己修改直到满意为止。

  以下是本人使用一个ToolStrip实现的一个简单的Demo,用户可以使用ToolStrip定制Form上任意Control的注释、字体、位置、尺寸以及前景色背景色。当用户没有点击任何Control的时候:

      

  用户点击了‘客户名’这个Label后:

     

  设置字体为‘黑体’,字号为‘10’,背景色,前景色:

     

  这个ToolStrip已经被包装成了一个Control,只需要把它拖到任意Form上,并在Form上接收所有Control的MouseClick事件,并把点击的Control设置给该ToolStrip的SelectedControl属性即可。

ToolStrip的源码:

 Code [http://www.xueit.com]
using System;
using System.Collections.Generic;
using System.Text;
using System.Windows.Forms;
using System.Drawing;

namespace GrapeCity.Cylj.ControlSetToolBar
{
    public class ControlSetToolBar : ToolStrip
    {
        public ControlSetToolBar()
        {
            this.InitializeComponent();
            System.Drawing.Text.InstalledFontCollection fonts = new System.Drawing.Text.InstalledFontCollection();
            foreach (System.Drawing.FontFamily font in fonts.Families)
            {
                this.font.Items.Add(font.Name);
            }
        }

        private Control selectedControl;

        public Control SelectedControl
        {
            get
            {
                return selectedControl;
            }
            set
            {
                if (value == null)
                {
                    this.Enabled = false;
                    this.comments.Text = "";
                    this.font.Text = "";
                    this.fontSize.Text = "";
                    this.xLocation.Text = "";
                    this.yLocation.Text = "";
                    this.width.Text = "";
                    this.height.Text = "";
                }
                if (this.selectedControl != value)
                {
                    this.Enabled = true;
                    selectedControl = value;
                    string comments = selectedControl.Tag == null ? "" : selectedControl.Tag.ToString();
                    if (string.IsNullOrEmpty(comments))
                    {
                        this.comments.TextChanged -= new EventHandler(comments_TextChanged);
                        this.comments.Text = "请在此输入注释";
                        this.comments.ForeColor = Color.Gray;
                        this.comments.TextChanged  = new EventHandler(comments_TextChanged);
                    }
                    else
                    {
                        this.comments.Text = comments;
                        this.comments.ForeColor = SystemColors.WindowText;
                    }
                    this.font.Text = selectedControl.Font.Name;
                    this.fontSize.Text = (int)Math.Round(selectedControl.Font.Size)   "";
                    this.xLocation.Text = selectedControl.Location.X   "";
                    this.yLocation.Text = selectedControl.Location.Y   "";
                    this.width.Text = selectedControl.Width   "";
                    this.height.Text = selectedControl.Height   "";
                    this.backColor.BackColor = selectedControl.BackColor;
                    this.backColor.ForeColor = selectedControl.ForeColor;
                    this.foreColor.BackColor = selectedControl.BackColor;
                    this.foreColor.ForeColor = selectedControl.ForeColor;
                }
            }
        }


        private ToolStripTextBox comments;
        private ToolStripLabel toolStripLabel1;
        private ToolStripLabel toolStripLabel2;
        private ToolStripComboBox font;
        private ToolStripLabel toolStripLabel3;
        private ToolStripComboBox fontSize;
        private ToolStripLabel toolStripLabel4;
        private ToolStripTextBox xLocation;
        private ToolStripLabel toolStripLabel5;
        private ToolStripTextBox yLocation;
        private ToolStripLabel toolStripLabel6;
        private ToolStripTextBox width;
        private ToolStripLabel toolStripLabel7;
        private ToolStripTextBox height;
        private ToolStripButton backColor;
        private ToolStripButton foreColor;
        private ToolStripSeparator toolStripSeparator1;
        private ToolStripSeparator toolStripSeparator2;
        private ToolStripSeparator toolStripSeparator3;

        private void InitializeComponent()
        {
            System.ComponentModel.ComponentResourceManager resources = new System.ComponentModel.ComponentResourceManager(typeof(ControlSetToolBar));
            this.comments = new System.Windows.Forms.ToolStripTextBox();
            this.toolStripLabel1 = new System.Windows.Forms.ToolStripLabel();
            this.toolStripLabel2 = new System.Windows.Forms.ToolStripLabel();
            this.font = new System.Windows.Forms.ToolStripComboBox();
            this.toolStripLabel3 = new System.Windows.Forms.ToolStripLabel();
            this.fontSize = new System.Windows.Forms.ToolStripComboBox();
            this.toolStripLabel4 = new System.Windows.Forms.ToolStripLabel();
            this.xLocation = new System.Windows.Forms.ToolStripTextBox();
            this.toolStripLabel5 = new System.Windows.Forms.ToolStripLabel();
            this.yLocation = new System.Windows.Forms.ToolStripTextBox();
            this.toolStripLabel6 = new System.Windows.Forms.ToolStripLabel();
            this.width = new System.Windows.Forms.ToolStripTextBox();
            this.toolStripLabel7 = new System.Windows.Forms.ToolStripLabel();
            this.height = new System.Windows.Forms.ToolStripTextBox();
            this.backColor = new System.Windows.Forms.ToolStripButton();
            this.foreColor = new System.Windows.Forms.ToolStripButton();
            this.toolStripSeparator1 = new ToolStripSeparator();
            this.toolStripSeparator2 = new ToolStripSeparator();
            this.toolStripSeparator3 = new ToolStripSeparator();
            this.SuspendLayout();
            //
            // toolStripTextBox1
            //
            this.comments.Name = "comments";
            this.comments.Size = new System.Drawing.Size(100, 21);
            this.comments.Text = "请在此输入注释";
            this.comments.TextChanged  = new EventHandler(comments_TextChanged);
            //
            // toolStripLabel1
            //
            this.toolStripLabel1.Name = "toolStripLabel1";
            this.toolStripLabel1.Size = new System.Drawing.Size(0, 22);
            //
            // toolStripLabel2
            //
            this.toolStripLabel2.Name = "toolStripLabel2";
            this.toolStripLabel2.Size = new System.Drawing.Size(29, 12);
            this.toolStripLabel2.Text = "字体";
            //
            // toolStripComboBox1
            //
            this.font.FlatStyle = System.Windows.Forms.FlatStyle.System;
            this.font.Name = "font";
            this.font.Size = new System.Drawing.Size(75, 20);
            this.font.TextChanged  = new EventHandler(font_TextChanged);
            //
            // toolStripLabel3
            //
            this.toolStripLabel3.Name = "toolStripLabel3";
            this.toolStripLabel3.Size = new System.Drawing.Size(29, 12);
            this.toolStripLabel3.Text = "字号";
            this.fontSize.TextChanged  = new EventHandler(fontSize_TextChanged);
            //
            // toolStripComboBox2
            //
            this.fontSize.Items.AddRange(new object[] {
            "8",
            "9",
            "10",
            "12",
            "14",
            "16"});
            this.fontSize.Name = "toolStripComboBox2";
            this.fontSize.Size = new System.Drawing.Size(75, 20);
            //
            // toolStripLabel4
            //
            this.toolStripLabel4.Name = "toolStripLabel4";
            this.toolStripLabel4.Size = new System.Drawing.Size(17, 12);
            this.toolStripLabel4.Text = "X:";
            //
            // toolStripTextBox2
            //
            this.xLocation.Name = "toolStripTextBox2";
            this.xLocation.Size = new System.Drawing.Size(30, 21);
            this.xLocation.TextChanged  = new EventHandler(xLocation_TextChanged);
            //
            // toolStripLabel5
            //
            this.toolStripLabel5.Name = "toolStripLabel5";
            this.toolStripLabel5.Size = new System.Drawing.Size(17, 12);
            this.toolStripLabel5.Text = "Y:";
            //
            // toolStripTextBox3
            //
            this.yLocation.Name = "toolStripTextBox3";
            this.yLocation.Size = new System.Drawing.Size(30, 21);
            this.yLocation.TextChanged  = new EventHandler(yLocation_TextChanged);
            //
            // toolStripLabel6
            //
            this.toolStripLabel6.Name = "toolStripLabel6";
            this.toolStripLabel6.Size = new System.Drawing.Size(23, 12);
            this.toolStripLabel6.Text = "宽:";
            //
            // toolStripTextBox4
            //
            this.width.Name = "toolStripTextBox4";
            this.width.Size = new System.Drawing.Size(30, 21);
            this.width.TextChanged  = new EventHandler(width_TextChanged);
            //
            // toolStripLabel7
            //
            this.toolStripLabel7.Name = "toolStripLabel7";
            this.toolStripLabel7.Size = new System.Drawing.Size(23, 12);
            this.toolStripLabel7.Text = "高:";
            //
            // toolStripTextBox5
            //
            this.height.Name = "toolStripTextBox5";
            this.height.Size = new System.Drawing.Size(30, 21);
            this.height.TextChanged  = new EventHandler(height_TextChanged);
            //
            // toolStripButton1
            //
            this.backColor.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
            this.backColor.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton1.Image")));
            this.backColor.ImageTransparentColor = System.Drawing.Color.Magenta;
            this.backColor.Name = "toolStripButton1";
            this.backColor.Size = new System.Drawing.Size(26, 22);
            this.backColor.Text = "背景色";
            this.backColor.Click  = new EventHandler(backColor_Click);
            this.backColor.Margin = new Padding(0, 0, 3, 0);
            //
            // toolStripButton2
            //
            this.foreColor.DisplayStyle = System.Windows.Forms.ToolStripItemDisplayStyle.Text;
            this.foreColor.Image = ((System.Drawing.Image)(resources.GetObject("toolStripButton2.Image")));
            this.foreColor.ImageTransparentColor = System.Drawing.Color.Magenta;
            this.foreColor.Name = "toolStripButton2";
            this.foreColor.Size = new System.Drawing.Size(26, 22);
            this.foreColor.Text = "前景色";
            this.foreColor.Click  = new EventHandler(foreColor_Click);
            //
            // ControlSetToolBar
            //
            this.Items.AddRange(new System.Windows.Forms.ToolStripItem[] {
            this.toolStripLabel1,
            this.comments,
            this.toolStripSeparator1,
            this.toolStripLabel2,
            this.font,
            this.toolStripLabel3,
            this.fontSize,
            this.toolStripLabel4,
            this.toolStripSeparator3,
            this.xLocation,
            this.toolStripLabel5,
            this.yLocation,
            this.toolStripLabel6,
            this.width,
            this.toolStripLabel7,
            this.height,
            this.toolStripSeparator3,
            this.backColor,
            this.foreColor});
            this.ResumeLayout(false);

        }

        void foreColor_Click(object sender, EventArgs e)
        {
            Color newColor;
            if (SetColor(this.selectedControl.ForeColor, out newColor))
            {
                this.selectedControl.ForeColor = newColor;
                this.foreColor.ForeColor = newColor;
                this.backColor.ForeColor = newColor;
            }
        }

        void backColor_Click(object sender, EventArgs e)
        {
            Color newColor;
            if (SetColor(this.selectedControl.BackColor, out newColor))
            {
                this.selectedControl.BackColor = newColor;
                this.foreColor.BackColor = newColor;
                this.backColor.BackColor = newColor;
            }
        }

        private bool SetColor(Color oldColor, out Color newColor)
        {
            ColorDialog dialog = new ColorDialog();
            dialog.Color = oldColor;
            DialogResult result = dialog.ShowDialog(this.selectedControl.FindForm());
            if (result == DialogResult.OK || result == DialogResult.Yes)
            {
                newColor = dialog.Color;
                return true;
            }
            newColor = oldColor;
            return false;
        }

        void height_TextChanged(object sender, EventArgs e)
        {
            if (this.selectedControl == null)
            {
                return;
            }
            int intValue;
            bool success = Int32.TryParse(this.height.Text, out intValue);
            if (!success)
            {
                this.height.Text = this.selectedControl.Height   "";
                return;
            }
            this.selectedControl.Height = intValue;
        }

        void width_TextChanged(object sender, EventArgs e)
        {
            if (this.selectedControl == null)
            {
                return;
            }
            int intValue;
            bool success = Int32.TryParse(this.width.Text, out intValue);
            if (!success)
            {
                this.width.Text = this.selectedControl.Width   "";
                return;
            }
            this.selectedControl.Width = intValue;
        }

        void yLocation_TextChanged(object sender, EventArgs e)
        {
            if (this.selectedControl == null)
            {
                return;
            }
            int intValue;
            bool success = Int32.TryParse(this.yLocation.Text, out intValue);
            if (!success)
            {
                this.yLocation.Text = this.selectedControl.Location.Y   "";
                return;
            }
            this.selectedControl.Location = new System.Drawing.Point(this.selectedControl.Location.X, intValue);
        }

        void xLocation_TextChanged(object sender, EventArgs e)
        {
            if (this.selectedControl == null)
            {
                return;
            }
            int intValue;
            bool success = Int32.TryParse( this.xLocation.Text, out intValue);
            if(!success)
            {
                this.xLocation.Text = this.selectedControl.Location.X   "";
                return;
            }
            this.selectedControl.Location = new System.Drawing.Point(intValue, this.selectedControl.Location.Y);
        }

        void fontSize_TextChanged(object sender, EventArgs e)
        {
            if (this.selectedControl == null)
            {
                return;
            }
            int intValue;
            bool success = Int32.TryParse(this.fontSize.Text, out intValue);
            if (!success)
            {
                this.fontSize.Text = Math.Round(this.selectedControl.Font.Size)   "";
                return;               
            }
            this.selectedControl.Font = new System.Drawing.Font(this.font.Text, intValue);
        }

        void font_TextChanged(object sender, EventArgs e)
        {
            if (this.selectedControl == null)
            {
                return;
            }
            if (this.font.SelectedItem != null)
            {
                this.selectedControl.Font = new System.Drawing.Font(this.font.SelectedItem.ToString(), this.selectedControl.Font.Size);               
            }
        }

        void comments_TextChanged(object sender, EventArgs e)
        {
            if (this.selectedControl == null)
            {
                return;
            }
            this.selectedControl.Tag = this.comments.Text;
            this.comments.ToolTipText = this.comments.Text;
        }
    }
}

Form的源码:

 Code
public Form1()
{
            InitializeComponent();
            AddEvents(this);
        }

        private void AddEvents(Control parentControl)
        {
            foreach (Control control in parentControl.Controls)
            {
                if (control == this.controlSetToolBar1)
                {
                    continue;
                }
control.MouseClick  = new MouseEventHandler(control_MouseClick);
                AddEvents(control);
            }           
        }

        void control_MouseClick(object sender, MouseEventArgs e)
        {
            Control control = sender as Control;
            if (control != null)
            {
                this.controlSetToolBar1.SelectedControl = control;
            }
        }

posted @ 2010-09-22 19:03  碧海蓝天_C#  阅读(494)  评论(0编辑  收藏  举报
官方QQ群:127876820【C#编程技术-全国站--未满人】