一个明确用户界面需求的想法
在應用程序開發中,需求不清晰從而導致需求變更是一個讓所有人深惡痛絕的事情,用戶界面也是其中很重要的部分。之所以用戶的需求不清晰是因為在很多時候,用戶的腦海中往往只會構思和想象用戶界面的一部分,他只能告訴你他想要的軟件大概是個什么樣子,有哪些功能和操作;你們也許會在紙上或者通過繪圖工具繪制一些用戶界面,這也不夠準確直觀;而讓用戶自己使用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的源碼:
代碼 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的源碼:
代碼 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;
}
}
?
?
?
當然,這只是本人的一個構想,尚沒有成功的商業案例。如何您對這個想法感興趣或者您還有些別的更好的做法,請回帖或者直接給我發信討論。
本篇是從Component對象到CodeDom——舞動你的Code系列(1)的應用,可以算作舞動你的Code系列(1.1)。如果你對設計器、VisualStudio擴展、序列化、控件設計等相關技術感興趣,歡迎訂閱收藏本博客。
轉載于:https://www.cnblogs.com/VisualStudioDesigner/archive/2010/09/21/1832393.html
總結
以上是生活随笔為你收集整理的一个明确用户界面需求的想法的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 企查查app如何更改手机号号码(企业工商
- 下一篇: QQ无法安装,不用着急,用毒霸2011来