(WPF学习记录)第六章 Dock与Grid
2008-09-16 08:42
197 查看
传统的程序具有相当标准的Layout,程序的菜单几乎是放在主窗口客户区的顶端,并延伸到整个窗口的宽度。如果程序有工具条,也是被dock(“停泊”)于客户区顶端,但是其中只有一个控件可以被停靠在最边缘。
WPF包含一个DockPanel类,可以满足不同的dock需求。
第01个小程序:DockPanel上的按钮(DockAroundTheBlock.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
class DockAroundTheBlock : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new DockAroundTheBlock());
}
public DockAroundTheBlock()
{
Title = "Dock Around the Block";
//Width = 384;
//Height = 288;
//SizeToContent = SizeToContent.WidthAndHeight;
DockPanel dock = new DockPanel();
//dock.LastChildFill = false; //默认为true,即最后一个孩子不被Dock.
Content = dock;
for (int i = 0; i < 17; i++)
{
Button btn = new Button();
btn.Content = "按钮" + (i + 1);
//btn.HorizontalAlignment = HorizontalAlignment.Center;
if (i % 4 == 0)
btn.Background = Brushes.Silver;
if (i % 4 == 1)
btn.Background = Brushes.SeaGreen;
if (i % 4 == 2)
btn.Background = Brushes.Salmon;
if (i % 4 == 3)
btn.Background = Brushes.RosyBrown;
if (i == 16)
btn.Background = Brushes.Pink;
dock.Children.Add(btn);
btn.SetValue(DockPanel.DockProperty, (Dock)(i % 4));
}
}
}
}
此程序建立一个DockPanel,并创建17个按钮当作它的孩子。
btn.SetValue(DockPanel.DockProperty, (Dock)(i % 4))等同于btn.SetDock(ctrl, (Dock)(i % 4)),决定让ctrl控件dock在DockPanel的哪一边。(Dock)(i % 4)为每个按钮循环地指定Dock枚举值,依次为:Dock.Left、Dock.Top、Dock.Right和Dock.Bottom(它们的枚举值分别为0、1、2和3)。
最后加入的控件(按钮17)并没有被dock,但是会占据剩余的内部空间,这是因为DockPanel的LastChildFill属性默认为true所导致的。虽然程序有为最后一个按钮调用SetValue,但是这个值会被忽略。当加入“dock.LastChildFill = false;”这条语句时,就可以看到最后一个按钮也会继续被dock,因而留下一些空间。
当使用DockPanel时,远近要从外向内:第一个孩子具有紧贴着父亲边缘的优先权,后续的孩子会越来越向里。
DockPanel的孩子通常会扩张到版面全部的宽度(或高度),这是因为孩子的HorizontalAlignment和VerticalAlignment属性默认值都是Stretch(延展)。
运行结果:
第02个小程序:DockPanel的使用(MeetTheDockers.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
public class MeetTheDockers : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new MeetTheDockers());
}
public MeetTheDockers()
{
Title = "Meet the Dockers";
Height = 288;
Width = 384;
WindowStartupLocation = WindowStartupLocation.CenterScreen;
DockPanel dock = new DockPanel();
Content = dock;
// 创建菜单
Menu menu = new Menu();
MenuItem item = new MenuItem();
item.Header = "菜单";
menu.Items.Add(item);
// 将菜单dock在面板顶端
DockPanel.SetDock(menu, Dock.Top);
dock.Children.Add(menu);
// 创建工具栏
ToolBar tool = new ToolBar();
tool.Header = "工具栏";
// 将工具栏dock在面板顶端(菜单下面)
DockPanel.SetDock(tool, Dock.Top);
dock.Children.Add(tool);
// 创建状态栏
StatusBar status = new StatusBar();
StatusBarItem statitem = new StatusBarItem();
statitem.Content = "状态栏";
status.Items.Add(statitem);
// 将状态栏dock在面板底端
DockPanel.SetDock(status, Dock.Bottom);
dock.Children.Add(status);
// 创建list box.
ListBox lstbox = new ListBox();
lstbox.Items.Add("List Box 项");
// 将list box对象dock在面板左边
DockPanel.SetDock(lstbox, Dock.Left);
dock.Children.Add(lstbox);
// 创建text box.
TextBox txtbox = new TextBox();
txtbox.AcceptsReturn = true;
// 将text box加入面板,并让它具有输入焦点
dock.Children.Add(txtbox);
txtbox.Focus();
}
}
}
这个程序创建了菜单、工具栏、状态栏、ListBox和TextBox控件,但没为它们加上实际的功能,只为演示使用DockPanel。
运行结果:
第03个小程序:计算你的年龄(CalculateYourLife.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
class CalculateYourLife : Window
{
TextBox txtboxBegin, txtboxEnd;
Label lblLifeYears;
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new CalculateYourLife());
}
public CalculateYourLife()
{
Title = "计算你的年龄";
Height = 140;
Width = 240;
WindowStartupLocation = WindowStartupLocation.CenterScreen;
//SizeToContent = SizeToContent.WidthAndHeight;
ResizeMode = ResizeMode.CanMinimize;
// 创建grid面板
Grid grid = new Grid();
//grid.ShowGridLines = true; //网格线可见。默认为false,不可见
Content = grid;
// 定义行和列
for (int i = 0; i < 3; i++) //三行
{
RowDefinition rowdef = new RowDefinition();
rowdef.Height = GridLength.Auto;
grid.RowDefinitions.Add(rowdef);
}
for (int i = 0; i < 2; i++) //两列
{
ColumnDefinition coldef = new ColumnDefinition();
coldef.Width = GridLength.Auto;
grid.ColumnDefinitions.Add(coldef);
}
// Label:出生日期
Label lbl = new Label();
lbl.Content = "出生日期: ";
grid.Children.Add(lbl);
Grid.SetRow(lbl, 0);
Grid.SetColumn(lbl, 0);
// TextBox:出生日期
txtboxBegin = new TextBox();
txtboxBegin.Width = 120;
txtboxBegin.Text = new DateTime(1111, 1, 1).ToShortDateString();
txtboxBegin.TextChanged += TextBoxOnTextChanged;
grid.Children.Add(txtboxBegin);
Grid.SetRow(txtboxBegin, 0);
Grid.SetColumn(txtboxBegin, 1);
// Label:当前日期
lbl = new Label();
lbl.Content = "当前日期: ";
grid.Children.Add(lbl);
Grid.SetRow(lbl, 1);
Grid.SetColumn(lbl, 0);
// TextBox::当前日期
txtboxEnd = new TextBox();
txtboxEnd.Width = 120;
txtboxEnd.Text = DateTime.Now.ToShortDateString();
txtboxEnd.TextChanged += TextBoxOnTextChanged;
grid.Children.Add(txtboxEnd);
Grid.SetRow(txtboxEnd, 1);
Grid.SetColumn(txtboxEnd, 1);
// Label:我的年龄
lbl = new Label();
lbl.Content = "我的年龄: ";
grid.Children.Add(lbl);
Grid.SetRow(lbl, 2);
Grid.SetColumn(lbl, 0);
// Label:计算结果
lblLifeYears = new Label();
grid.Children.Add(lblLifeYears);
Grid.SetRow(lblLifeYears, 2);
Grid.SetColumn(lblLifeYears, 1);
// 设置边界
Thickness thick = new Thickness(5);
grid.Margin = thick;
foreach (Control ctrl in grid.Children)
ctrl.Margin = thick;
// 设定焦点
txtboxBegin.Focus();
// 计算
Calculating();
}
// TextBox中的值改变后,计算年龄
void TextBoxOnTextChanged(object sender, TextChangedEventArgs args)
{
Calculating();
}
// 计算年龄
private void Calculating()
{
DateTime dtBeg, dtEnd;
if (DateTime.TryParse(txtboxBegin.Text, out dtBeg) &
DateTime.TryParse(txtboxEnd.Text, out dtEnd))
{
int iYears = dtEnd.Year - dtBeg.Year;
int iMonths = dtEnd.Month - dtBeg.Month;
int iDays = dtEnd.Day - dtBeg.Day;
if (iDays < 0)
{
iDays += DateTime.DaysInMonth(dtEnd.Year,
1 + (dtEnd.Month + 10) % 12);
iMonths -= 1;
}
if (iMonths < 0)
{
iMonths += 12;
iYears -= 1;
}
//lblLifeYears.Content =
// String.Format("{0} year{1}, {2} month{3}, {4} day{5}",
// iYears, iYears == 1 ? "" : "s",
// iMonths, iMonths == 1 ? "" : "s",
// iDays, iDays == 1 ? "" : "s");
lblLifeYears.Content =
String.Format("{0}岁{1}个月零{2}天",
iYears,
iMonths,
iDays);
}
else
{
lblLifeYears.Content = "";
}
}
}
}
Grid面板用行和列的格子状来显示其孩子,来实现行与列的控件布局。
使用GridLength类以指定行的高度和列的宽度。此类有两个构造函数:
new GridLength(100),这个值是独立单位,这样的构造函数等同于new GridLength(100, GridUnitType.Pixel)。也可以用GridUnitType.Star来当作第二个参数,如new GridLength(50, GridUnitType.Star),表示将剩余空间的50%分配给该行(列)。当用GridUnitType.Auto作为第二个参数时,如new GridLength(50, GridUnitType.Auto),这个数字会被忽略,等同静态的属性:GridLength.Auto。
Grid的静态方法SetRow和SetColumn方法,指定一个row和column索引值,以表示控件要摆放的位置。如:Grid.SetRow(lbl, 2),Grid.SetColumn(lbl, 0)。
程序运行结果如下:
第04个小程序:Grid布局(EnterTheGrid.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
public class EnterTheGrid : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new EnterTheGrid());
}
public EnterTheGrid()
{
Title = "又见Grid";
MinWidth = 300; //最小宽度
WindowStartupLocation = WindowStartupLocation.CenterScreen;
SizeToContent = SizeToContent.WidthAndHeight;
// 创建StackPanel对象
StackPanel stack = new StackPanel();
Content = stack;
// 创建Grid并将其加入StackPanel
Grid grid1 = new Grid();
grid1.Margin = new Thickness(5);
stack.Children.Add(grid1);
// 定义行
for (int i = 0; i < 5; i++)
{
RowDefinition rowdef = new RowDefinition();
rowdef.Height = GridLength.Auto;
grid1.RowDefinitions.Add(rowdef);
}
// 定义列
ColumnDefinition coldef = new ColumnDefinition();
coldef.Width = GridLength.Auto;
grid1.ColumnDefinitions.Add(coldef);
// 第2列
coldef = new ColumnDefinition();
coldef.Width = new GridLength(100, GridUnitType.Star); //占据剩余空间
grid1.ColumnDefinitions.Add(coldef);
// 创建labels和text boxes.
string[] strLabels = { "姓:", "名:",
"身份证号码:",
"信用卡号码:",
"其它:" };
for(int i = 0; i < strLabels.Length; i++)
{
// 创建Label
Label lbl = new Label();
lbl.Content = strLabels[i];
lbl.VerticalContentAlignment = VerticalAlignment.Center;
grid1.Children.Add(lbl);
Grid.SetRow(lbl, i); //Label在第i+1行
Grid.SetColumn(lbl, 0); //Label在第1列
// 创建TextBox
TextBox txtbox = new TextBox();
txtbox.Margin = new Thickness(5);
grid1.Children.Add(txtbox);
Grid.SetRow(txtbox, i); //TextBox在第i+1行
Grid.SetColumn(txtbox, 1); //TextBox在第2列
}
// 创建第二个Grid并将其加入StackPanel
Grid grid2 = new Grid();
grid2.Margin = new Thickness(10);
stack.Children.Add(grid2);
// 对于单一行,不需要row定义
// 默认列定义 “star”
grid2.ColumnDefinitions.Add(new ColumnDefinition());
grid2.ColumnDefinitions.Add(new ColumnDefinition());
// 创建按钮
Button btn = new Button();
btn.Content = "提交";
btn.HorizontalAlignment = HorizontalAlignment.Center;
btn.IsDefault = true;
//btn.Click += delegate { Close(); };
btn.Click += ButtonSubClick;
grid2.Children.Add(btn); // 行号和列号都为0
btn = new Button();
btn.Content = "取消";
btn.HorizontalAlignment = HorizontalAlignment.Center;
btn.IsCancel = true;
//btn.Click += delegate { Close(); };
btn.Click += ButtonCanClick;
grid2.Children.Add(btn);
Grid.SetColumn(btn, 1); //行0,列1
// 为第一个TextBox设置焦点
(stack.Children[0] as Panel).Children[1].Focus();
}
void ButtonSubClick(object sender, RoutedEventArgs args)
{
MessageBox.Show("提交成功!","个人信息");
this.Close();
}
void ButtonCanClick(object sender, RoutedEventArgs args)
{
MessageBox.Show("重新填写!", "个人信息");
}
}
}
程序依赖元素默认的行为来填满他们的父亲。StackPanel占用窗口整个宽度,两个Grid面板也是。在最顶端的Grid面板中,第一列具有GridLength.Auto的宽度;第二列(有TextBox的列)的宽度为GridUnitType.Star式,即会占用所有剩余空间。所以当窗口变宽时,TextBox也会扩展宽度;当TextBox控件内文本超过其初始长度时,TextBox和窗口也会扩大。
运行结果:
第05个小程序:跨越单元格(SpanTheCells.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
public class SpanTheCells : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new SpanTheCells());
}
public SpanTheCells()
{
Title = "跨越单元格";
MinWidth = 300; //最小宽度
WindowStartupLocation = WindowStartupLocation.CenterScreen;
SizeToContent = SizeToContent.WidthAndHeight;
// 创建Grid
Grid grid = new Grid();
grid.ShowGridLines = true; //显示网格线
grid.Margin = new Thickness(5);
Content = grid;
// 定义行,6行
for (int i = 0; i < 6; i++)
{
RowDefinition rowdef = new RowDefinition();
rowdef.Height = GridLength.Auto;
grid.RowDefinitions.Add(rowdef);
}
// 定义列,4列
for (int i = 0; i < 4; i++)
{
ColumnDefinition coldef = new ColumnDefinition();
// 第1列占据剩余空间,其余列自动排列
if (i == 1)
coldef.Width = new GridLength(100, GridUnitType.Star);
else
coldef.Width = GridLength.Auto;
grid.ColumnDefinitions.Add(coldef);
}
// 创建labels和text boxes
string[] strLabels = { "姓:", "名:",
"身份证号码:",
"信用卡号码:",
"其它:" };
for(int i = 0; i < strLabels.Length; i++)
{
Label lbl = new Label();
lbl.Content = strLabels[i];
lbl.VerticalContentAlignment = VerticalAlignment.Center;
grid.Children.Add(lbl);
Grid.SetRow(lbl, i); //Label放在第i+1行
Grid.SetColumn(lbl, 0); //Label放在第1列
TextBox txtbox = new TextBox();
txtbox.Margin = new Thickness(5);
grid.Children.Add(txtbox);
Grid.SetRow(txtbox, i); //TextBox放在第i+1行
Grid.SetColumn(txtbox, 1); //TextBox放在第2列
Grid.SetColumnSpan(txtbox, 3); //TextBox跨越到最后一列(第4列)
}
// 创建按钮
Button btn = new Button();
btn.Content = "提交";
btn.Margin = new Thickness(5);
btn.IsDefault = true;
btn.Click += delegate { Close(); };
grid.Children.Add(btn);
Grid.SetRow(btn, 5); //"提交"按钮放在第6行
Grid.SetColumn(btn, 2); //"提交"按钮放在第3列
btn = new Button();
btn.Content = "取消";
btn.Margin = new Thickness(5);
btn.IsCancel = true;
btn.Click += delegate { Close(); };
grid.Children.Add(btn);
Grid.SetRow(btn, 5); //"取消"按钮放在第6行
Grid.SetColumn(btn, 3); //"取消"按钮放在第4列
// 为第一个TextBox设置焦点
grid.Children[1].Focus();
}
}
}
这个程序和上一个相像,不同的是只使用一个6行4列的Grid面板,编辑框(TextBox)跨越占用2、3、4列。
指定元素占用的列的个数是用Grid.SetColumnSpan(txtbox, 3)实现的,类似占用行个数的设置方法是Grid.SetRowSpan(ctrl, 2)。
运行结果如下,这里设置显示Grid网格线,很容易看出控件布局格式:
第06个小程序:分隔线(SplitNine.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
public class SplitNine : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new SplitNine());
}
public SplitNine()
{
Title = "分隔线";
Grid grid = new Grid();
Content = grid;
// 定义行和列
for (int i = 0; i < 3; i++)
{
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.RowDefinitions.Add(new RowDefinition());
}
// 创建9个按钮
for (int x = 0; x < 3; x++)
for (int y = 0; y < 3; y++)
{
Button btn = new Button();
btn.Content = "第" + (y + 1) + "行 第" + (x + 1) + "列";
btn.Margin = new Thickness(10);
grid.Children.Add(btn);
Grid.SetRow(btn, y);
Grid.SetColumn(btn, x);
}
// 创建splitter,指派其位置。此处位于第2行第2列处
GridSplitter split = new GridSplitter();
split.Width = 2;
split.Background = Brushes.Green;
grid.Children.Add(split);
Grid.SetRow(split, 1);
Grid.SetColumn(split, 1);
}
}
}
运行后,在第2行第2列后会出现一条绿色的线,移动它时,不同行的列的宽度也会跟着改变。
运行结果如下:
第07个小程序:分隔客户区(SplitTheClient.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
class SplitTheClient : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new SplitTheClient());
}
public SplitTheClient()
{
Title = "分隔客户区";
Height = 288;
Width = 480;
WindowStartupLocation = WindowStartupLocation.CenterScreen;
// 具有垂直splitter的Grid
// 单行,无需设置row
// 3列:第1列放按钮1,第2列放垂直splitter,第3列放grid2
Grid grid1 = new Grid();
grid1.ColumnDefinitions.Add(new ColumnDefinition());
grid1.ColumnDefinitions.Add(new ColumnDefinition());
grid1.ColumnDefinitions.Add(new ColumnDefinition());
grid1.ColumnDefinitions[1].Width = GridLength.Auto;
Content = grid1;
// 垂直splitter左边的Button
Button btn = new Button();
btn.Content = "按钮1";
grid1.Children.Add(btn);
Grid.SetRow(btn, 0);
Grid.SetColumn(btn, 0);
// 垂直splitter.
GridSplitter split = new GridSplitter();
split.ShowsPreview = true;
split.Background = Brushes.Blue;
split.HorizontalAlignment = HorizontalAlignment.Center;
split.VerticalAlignment = VerticalAlignment.Stretch;
split.Width = 6;
grid1.Children.Add(split);
Grid.SetRow(split, 0);
Grid.SetColumn(split, 1);
// 具有水平splitter的Grid
// 3行:第1行放按钮2,第2行放水平splitter,第3行放按钮3
// 单列,无需设置column
Grid grid2 = new Grid();
grid2.RowDefinitions.Add(new RowDefinition());
grid2.RowDefinitions.Add(new RowDefinition());
grid2.RowDefinitions.Add(new RowDefinition());
grid2.RowDefinitions[1].Height = GridLength.Auto;
grid1.Children.Add(grid2);
Grid.SetRow(grid2, 0);
Grid.SetColumn(grid2, 2);
// 水平splitter上方的Button
btn = new Button();
btn.Content = "按钮2";
grid2.Children.Add(btn);
Grid.SetRow(btn, 0);
Grid.SetColumn(btn, 0);
// 水平splitter.
split = new GridSplitter();
split.ShowsPreview = true;
split.Background = Brushes.Blue;
split.HorizontalAlignment = HorizontalAlignment.Stretch;
split.VerticalAlignment = VerticalAlignment.Center;
split.Height = 6;
grid2.Children.Add(split);
Grid.SetRow(split, 1);
Grid.SetColumn(split, 0);
// 水平splitter底部的Button
btn = new Button();
btn.Content = "按钮3";
grid2.Children.Add(btn);
Grid.SetRow(btn, 2);
Grid.SetColumn(btn, 0);
}
}
}
运行结果:
第08个小程序:颜色卷轴(ColorScroll.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
namespace Chapter06
{
class ColorScroll : Window
{
ScrollBar[] scrolls = new ScrollBar[3];
TextBlock[] txtValue = new TextBlock[3];
Panel pnlColor;
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new ColorScroll());
}
public ColorScroll()
{
Title = "颜色卷轴";
Width = 500;
Height = 300;
WindowStartupLocation = WindowStartupLocation.CenterScreen;
// 包含垂直splitter的GridMain
Grid gridMain = new Grid();
//gridMain.ShowGridLines = true;
Content = gridMain;
// GridMain的列定义
// 3列:第1列放grid,第2列放垂直splitter,第3列放颜色面板pnlColor
ColumnDefinition coldef = new ColumnDefinition();
coldef.Width = new GridLength(200, GridUnitType.Pixel);
gridMain.ColumnDefinitions.Add(coldef);
coldef = new ColumnDefinition();
coldef.Width = GridLength.Auto;
gridMain.ColumnDefinitions.Add(coldef);
coldef = new ColumnDefinition();
coldef.Width = new GridLength(100, GridUnitType.Star);
gridMain.ColumnDefinitions.Add(coldef);
// 垂直splitter
GridSplitter split = new GridSplitter();
split.HorizontalAlignment = HorizontalAlignment.Center;
split.VerticalAlignment = VerticalAlignment.Stretch;
split.Width = 6;
gridMain.Children.Add(split);
Grid.SetRow(split, 0);
Grid.SetColumn(split, 1);
// splitter右边的面板,用来显示颜色
pnlColor = new StackPanel();
pnlColor.Background = new SolidColorBrush(SystemColors.WindowColor);
gridMain.Children.Add(pnlColor);
Grid.SetRow(pnlColor, 0);
Grid.SetColumn(pnlColor, 2);
// 左边的第2个Grid,将其加入gridMain
Grid grid = new Grid();
//grid.ShowGridLines = true;
gridMain.Children.Add(grid);
Grid.SetRow(grid, 0);
Grid.SetColumn(grid, 0);
// 定义3行,分别放置label,scroll和label
RowDefinition rowdef = new RowDefinition();
rowdef.Height = GridLength.Auto;
grid.RowDefinitions.Add(rowdef);
rowdef = new RowDefinition();
rowdef.Height = new GridLength(100, GridUnitType.Star);
grid.RowDefinitions.Add(rowdef);
rowdef = new RowDefinition();
rowdef.Height = GridLength.Auto;
grid.RowDefinitions.Add(rowdef);
// 3列:红、绿、蓝
for (int i = 0; i < 3; i++)
{
coldef = new ColumnDefinition();
coldef.Width = new GridLength(33, GridUnitType.Star);
grid.ColumnDefinitions.Add(coldef);
}
for (int i = 0; i < 3; i++)
{
Label lbl = new Label();
lbl.Content = new string[] { "红", "绿", "蓝" }[i];
lbl.HorizontalAlignment = HorizontalAlignment.Center;
grid.Children.Add(lbl);
Grid.SetRow(lbl, 0);
Grid.SetColumn(lbl, i);
scrolls[i] = new ScrollBar();
scrolls[i].Focusable = true;
scrolls[i].Orientation = Orientation.Vertical;
scrolls[i].Minimum = 0;
scrolls[i].Maximum = 255;
scrolls[i].SmallChange = 1;
scrolls[i].LargeChange = 16;
scrolls[i].ValueChanged += ScrollOnValueChanged;
grid.Children.Add(scrolls[i]);
Grid.SetRow(scrolls[i], 1);
Grid.SetColumn(scrolls[i], i);
txtValue[i] = new TextBlock();
txtValue[i].TextAlignment = TextAlignment.Center;
txtValue[i].HorizontalAlignment = HorizontalAlignment.Center;
txtValue[i].Margin = new Thickness(5);
grid.Children.Add(txtValue[i]);
Grid.SetRow(txtValue[i], 2);
Grid.SetColumn(txtValue[i], i);
}
// 初始化卷轴
Color clr = (pnlColor.Background as SolidColorBrush).Color;
scrolls[0].Value = clr.R;
scrolls[1].Value = clr.G;
scrolls[2].Value = clr.B;
// 设置初始焦点
scrolls[0].Focus();
}
void ScrollOnValueChanged(object sender, RoutedEventArgs args)
{
ScrollBar scroll = sender as ScrollBar;
Panel pnl = scroll.Parent as Panel;
TextBlock txt = pnl.Children[1 +
pnl.Children.IndexOf(scroll)] as TextBlock;
txt.Text = String.Format("{0}/n0x{0:X2}", (int)scroll.Value); //RGB和16进制显示
pnlColor.Background =
new SolidColorBrush(
Color.FromRgb((byte)scrolls[0].Value,
(byte)scrolls[1].Value, (byte)scrolls[2].Value));
}
}
}
ScrollOnValueChanged事件处理器负责将ScroolBar的值更新到TextBlock,然后根据这3个滚动条的值计算出一个新的Color,显示在Color面板。
运行效果:
WPF包含一个DockPanel类,可以满足不同的dock需求。
第01个小程序:DockPanel上的按钮(DockAroundTheBlock.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
class DockAroundTheBlock : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new DockAroundTheBlock());
}
public DockAroundTheBlock()
{
Title = "Dock Around the Block";
//Width = 384;
//Height = 288;
//SizeToContent = SizeToContent.WidthAndHeight;
DockPanel dock = new DockPanel();
//dock.LastChildFill = false; //默认为true,即最后一个孩子不被Dock.
Content = dock;
for (int i = 0; i < 17; i++)
{
Button btn = new Button();
btn.Content = "按钮" + (i + 1);
//btn.HorizontalAlignment = HorizontalAlignment.Center;
if (i % 4 == 0)
btn.Background = Brushes.Silver;
if (i % 4 == 1)
btn.Background = Brushes.SeaGreen;
if (i % 4 == 2)
btn.Background = Brushes.Salmon;
if (i % 4 == 3)
btn.Background = Brushes.RosyBrown;
if (i == 16)
btn.Background = Brushes.Pink;
dock.Children.Add(btn);
btn.SetValue(DockPanel.DockProperty, (Dock)(i % 4));
}
}
}
}
此程序建立一个DockPanel,并创建17个按钮当作它的孩子。
btn.SetValue(DockPanel.DockProperty, (Dock)(i % 4))等同于btn.SetDock(ctrl, (Dock)(i % 4)),决定让ctrl控件dock在DockPanel的哪一边。(Dock)(i % 4)为每个按钮循环地指定Dock枚举值,依次为:Dock.Left、Dock.Top、Dock.Right和Dock.Bottom(它们的枚举值分别为0、1、2和3)。
最后加入的控件(按钮17)并没有被dock,但是会占据剩余的内部空间,这是因为DockPanel的LastChildFill属性默认为true所导致的。虽然程序有为最后一个按钮调用SetValue,但是这个值会被忽略。当加入“dock.LastChildFill = false;”这条语句时,就可以看到最后一个按钮也会继续被dock,因而留下一些空间。
当使用DockPanel时,远近要从外向内:第一个孩子具有紧贴着父亲边缘的优先权,后续的孩子会越来越向里。
DockPanel的孩子通常会扩张到版面全部的宽度(或高度),这是因为孩子的HorizontalAlignment和VerticalAlignment属性默认值都是Stretch(延展)。
运行结果:
第02个小程序:DockPanel的使用(MeetTheDockers.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
public class MeetTheDockers : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new MeetTheDockers());
}
public MeetTheDockers()
{
Title = "Meet the Dockers";
Height = 288;
Width = 384;
WindowStartupLocation = WindowStartupLocation.CenterScreen;
DockPanel dock = new DockPanel();
Content = dock;
// 创建菜单
Menu menu = new Menu();
MenuItem item = new MenuItem();
item.Header = "菜单";
menu.Items.Add(item);
// 将菜单dock在面板顶端
DockPanel.SetDock(menu, Dock.Top);
dock.Children.Add(menu);
// 创建工具栏
ToolBar tool = new ToolBar();
tool.Header = "工具栏";
// 将工具栏dock在面板顶端(菜单下面)
DockPanel.SetDock(tool, Dock.Top);
dock.Children.Add(tool);
// 创建状态栏
StatusBar status = new StatusBar();
StatusBarItem statitem = new StatusBarItem();
statitem.Content = "状态栏";
status.Items.Add(statitem);
// 将状态栏dock在面板底端
DockPanel.SetDock(status, Dock.Bottom);
dock.Children.Add(status);
// 创建list box.
ListBox lstbox = new ListBox();
lstbox.Items.Add("List Box 项");
// 将list box对象dock在面板左边
DockPanel.SetDock(lstbox, Dock.Left);
dock.Children.Add(lstbox);
// 创建text box.
TextBox txtbox = new TextBox();
txtbox.AcceptsReturn = true;
// 将text box加入面板,并让它具有输入焦点
dock.Children.Add(txtbox);
txtbox.Focus();
}
}
}
这个程序创建了菜单、工具栏、状态栏、ListBox和TextBox控件,但没为它们加上实际的功能,只为演示使用DockPanel。
运行结果:
第03个小程序:计算你的年龄(CalculateYourLife.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
class CalculateYourLife : Window
{
TextBox txtboxBegin, txtboxEnd;
Label lblLifeYears;
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new CalculateYourLife());
}
public CalculateYourLife()
{
Title = "计算你的年龄";
Height = 140;
Width = 240;
WindowStartupLocation = WindowStartupLocation.CenterScreen;
//SizeToContent = SizeToContent.WidthAndHeight;
ResizeMode = ResizeMode.CanMinimize;
// 创建grid面板
Grid grid = new Grid();
//grid.ShowGridLines = true; //网格线可见。默认为false,不可见
Content = grid;
// 定义行和列
for (int i = 0; i < 3; i++) //三行
{
RowDefinition rowdef = new RowDefinition();
rowdef.Height = GridLength.Auto;
grid.RowDefinitions.Add(rowdef);
}
for (int i = 0; i < 2; i++) //两列
{
ColumnDefinition coldef = new ColumnDefinition();
coldef.Width = GridLength.Auto;
grid.ColumnDefinitions.Add(coldef);
}
// Label:出生日期
Label lbl = new Label();
lbl.Content = "出生日期: ";
grid.Children.Add(lbl);
Grid.SetRow(lbl, 0);
Grid.SetColumn(lbl, 0);
// TextBox:出生日期
txtboxBegin = new TextBox();
txtboxBegin.Width = 120;
txtboxBegin.Text = new DateTime(1111, 1, 1).ToShortDateString();
txtboxBegin.TextChanged += TextBoxOnTextChanged;
grid.Children.Add(txtboxBegin);
Grid.SetRow(txtboxBegin, 0);
Grid.SetColumn(txtboxBegin, 1);
// Label:当前日期
lbl = new Label();
lbl.Content = "当前日期: ";
grid.Children.Add(lbl);
Grid.SetRow(lbl, 1);
Grid.SetColumn(lbl, 0);
// TextBox::当前日期
txtboxEnd = new TextBox();
txtboxEnd.Width = 120;
txtboxEnd.Text = DateTime.Now.ToShortDateString();
txtboxEnd.TextChanged += TextBoxOnTextChanged;
grid.Children.Add(txtboxEnd);
Grid.SetRow(txtboxEnd, 1);
Grid.SetColumn(txtboxEnd, 1);
// Label:我的年龄
lbl = new Label();
lbl.Content = "我的年龄: ";
grid.Children.Add(lbl);
Grid.SetRow(lbl, 2);
Grid.SetColumn(lbl, 0);
// Label:计算结果
lblLifeYears = new Label();
grid.Children.Add(lblLifeYears);
Grid.SetRow(lblLifeYears, 2);
Grid.SetColumn(lblLifeYears, 1);
// 设置边界
Thickness thick = new Thickness(5);
grid.Margin = thick;
foreach (Control ctrl in grid.Children)
ctrl.Margin = thick;
// 设定焦点
txtboxBegin.Focus();
// 计算
Calculating();
}
// TextBox中的值改变后,计算年龄
void TextBoxOnTextChanged(object sender, TextChangedEventArgs args)
{
Calculating();
}
// 计算年龄
private void Calculating()
{
DateTime dtBeg, dtEnd;
if (DateTime.TryParse(txtboxBegin.Text, out dtBeg) &
DateTime.TryParse(txtboxEnd.Text, out dtEnd))
{
int iYears = dtEnd.Year - dtBeg.Year;
int iMonths = dtEnd.Month - dtBeg.Month;
int iDays = dtEnd.Day - dtBeg.Day;
if (iDays < 0)
{
iDays += DateTime.DaysInMonth(dtEnd.Year,
1 + (dtEnd.Month + 10) % 12);
iMonths -= 1;
}
if (iMonths < 0)
{
iMonths += 12;
iYears -= 1;
}
//lblLifeYears.Content =
// String.Format("{0} year{1}, {2} month{3}, {4} day{5}",
// iYears, iYears == 1 ? "" : "s",
// iMonths, iMonths == 1 ? "" : "s",
// iDays, iDays == 1 ? "" : "s");
lblLifeYears.Content =
String.Format("{0}岁{1}个月零{2}天",
iYears,
iMonths,
iDays);
}
else
{
lblLifeYears.Content = "";
}
}
}
}
Grid面板用行和列的格子状来显示其孩子,来实现行与列的控件布局。
使用GridLength类以指定行的高度和列的宽度。此类有两个构造函数:
new GridLength(100),这个值是独立单位,这样的构造函数等同于new GridLength(100, GridUnitType.Pixel)。也可以用GridUnitType.Star来当作第二个参数,如new GridLength(50, GridUnitType.Star),表示将剩余空间的50%分配给该行(列)。当用GridUnitType.Auto作为第二个参数时,如new GridLength(50, GridUnitType.Auto),这个数字会被忽略,等同静态的属性:GridLength.Auto。
Grid的静态方法SetRow和SetColumn方法,指定一个row和column索引值,以表示控件要摆放的位置。如:Grid.SetRow(lbl, 2),Grid.SetColumn(lbl, 0)。
程序运行结果如下:
第04个小程序:Grid布局(EnterTheGrid.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
public class EnterTheGrid : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new EnterTheGrid());
}
public EnterTheGrid()
{
Title = "又见Grid";
MinWidth = 300; //最小宽度
WindowStartupLocation = WindowStartupLocation.CenterScreen;
SizeToContent = SizeToContent.WidthAndHeight;
// 创建StackPanel对象
StackPanel stack = new StackPanel();
Content = stack;
// 创建Grid并将其加入StackPanel
Grid grid1 = new Grid();
grid1.Margin = new Thickness(5);
stack.Children.Add(grid1);
// 定义行
for (int i = 0; i < 5; i++)
{
RowDefinition rowdef = new RowDefinition();
rowdef.Height = GridLength.Auto;
grid1.RowDefinitions.Add(rowdef);
}
// 定义列
ColumnDefinition coldef = new ColumnDefinition();
coldef.Width = GridLength.Auto;
grid1.ColumnDefinitions.Add(coldef);
// 第2列
coldef = new ColumnDefinition();
coldef.Width = new GridLength(100, GridUnitType.Star); //占据剩余空间
grid1.ColumnDefinitions.Add(coldef);
// 创建labels和text boxes.
string[] strLabels = { "姓:", "名:",
"身份证号码:",
"信用卡号码:",
"其它:" };
for(int i = 0; i < strLabels.Length; i++)
{
// 创建Label
Label lbl = new Label();
lbl.Content = strLabels[i];
lbl.VerticalContentAlignment = VerticalAlignment.Center;
grid1.Children.Add(lbl);
Grid.SetRow(lbl, i); //Label在第i+1行
Grid.SetColumn(lbl, 0); //Label在第1列
// 创建TextBox
TextBox txtbox = new TextBox();
txtbox.Margin = new Thickness(5);
grid1.Children.Add(txtbox);
Grid.SetRow(txtbox, i); //TextBox在第i+1行
Grid.SetColumn(txtbox, 1); //TextBox在第2列
}
// 创建第二个Grid并将其加入StackPanel
Grid grid2 = new Grid();
grid2.Margin = new Thickness(10);
stack.Children.Add(grid2);
// 对于单一行,不需要row定义
// 默认列定义 “star”
grid2.ColumnDefinitions.Add(new ColumnDefinition());
grid2.ColumnDefinitions.Add(new ColumnDefinition());
// 创建按钮
Button btn = new Button();
btn.Content = "提交";
btn.HorizontalAlignment = HorizontalAlignment.Center;
btn.IsDefault = true;
//btn.Click += delegate { Close(); };
btn.Click += ButtonSubClick;
grid2.Children.Add(btn); // 行号和列号都为0
btn = new Button();
btn.Content = "取消";
btn.HorizontalAlignment = HorizontalAlignment.Center;
btn.IsCancel = true;
//btn.Click += delegate { Close(); };
btn.Click += ButtonCanClick;
grid2.Children.Add(btn);
Grid.SetColumn(btn, 1); //行0,列1
// 为第一个TextBox设置焦点
(stack.Children[0] as Panel).Children[1].Focus();
}
void ButtonSubClick(object sender, RoutedEventArgs args)
{
MessageBox.Show("提交成功!","个人信息");
this.Close();
}
void ButtonCanClick(object sender, RoutedEventArgs args)
{
MessageBox.Show("重新填写!", "个人信息");
}
}
}
程序依赖元素默认的行为来填满他们的父亲。StackPanel占用窗口整个宽度,两个Grid面板也是。在最顶端的Grid面板中,第一列具有GridLength.Auto的宽度;第二列(有TextBox的列)的宽度为GridUnitType.Star式,即会占用所有剩余空间。所以当窗口变宽时,TextBox也会扩展宽度;当TextBox控件内文本超过其初始长度时,TextBox和窗口也会扩大。
运行结果:
第05个小程序:跨越单元格(SpanTheCells.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
public class SpanTheCells : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new SpanTheCells());
}
public SpanTheCells()
{
Title = "跨越单元格";
MinWidth = 300; //最小宽度
WindowStartupLocation = WindowStartupLocation.CenterScreen;
SizeToContent = SizeToContent.WidthAndHeight;
// 创建Grid
Grid grid = new Grid();
grid.ShowGridLines = true; //显示网格线
grid.Margin = new Thickness(5);
Content = grid;
// 定义行,6行
for (int i = 0; i < 6; i++)
{
RowDefinition rowdef = new RowDefinition();
rowdef.Height = GridLength.Auto;
grid.RowDefinitions.Add(rowdef);
}
// 定义列,4列
for (int i = 0; i < 4; i++)
{
ColumnDefinition coldef = new ColumnDefinition();
// 第1列占据剩余空间,其余列自动排列
if (i == 1)
coldef.Width = new GridLength(100, GridUnitType.Star);
else
coldef.Width = GridLength.Auto;
grid.ColumnDefinitions.Add(coldef);
}
// 创建labels和text boxes
string[] strLabels = { "姓:", "名:",
"身份证号码:",
"信用卡号码:",
"其它:" };
for(int i = 0; i < strLabels.Length; i++)
{
Label lbl = new Label();
lbl.Content = strLabels[i];
lbl.VerticalContentAlignment = VerticalAlignment.Center;
grid.Children.Add(lbl);
Grid.SetRow(lbl, i); //Label放在第i+1行
Grid.SetColumn(lbl, 0); //Label放在第1列
TextBox txtbox = new TextBox();
txtbox.Margin = new Thickness(5);
grid.Children.Add(txtbox);
Grid.SetRow(txtbox, i); //TextBox放在第i+1行
Grid.SetColumn(txtbox, 1); //TextBox放在第2列
Grid.SetColumnSpan(txtbox, 3); //TextBox跨越到最后一列(第4列)
}
// 创建按钮
Button btn = new Button();
btn.Content = "提交";
btn.Margin = new Thickness(5);
btn.IsDefault = true;
btn.Click += delegate { Close(); };
grid.Children.Add(btn);
Grid.SetRow(btn, 5); //"提交"按钮放在第6行
Grid.SetColumn(btn, 2); //"提交"按钮放在第3列
btn = new Button();
btn.Content = "取消";
btn.Margin = new Thickness(5);
btn.IsCancel = true;
btn.Click += delegate { Close(); };
grid.Children.Add(btn);
Grid.SetRow(btn, 5); //"取消"按钮放在第6行
Grid.SetColumn(btn, 3); //"取消"按钮放在第4列
// 为第一个TextBox设置焦点
grid.Children[1].Focus();
}
}
}
这个程序和上一个相像,不同的是只使用一个6行4列的Grid面板,编辑框(TextBox)跨越占用2、3、4列。
指定元素占用的列的个数是用Grid.SetColumnSpan(txtbox, 3)实现的,类似占用行个数的设置方法是Grid.SetRowSpan(ctrl, 2)。
运行结果如下,这里设置显示Grid网格线,很容易看出控件布局格式:
第06个小程序:分隔线(SplitNine.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
public class SplitNine : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new SplitNine());
}
public SplitNine()
{
Title = "分隔线";
Grid grid = new Grid();
Content = grid;
// 定义行和列
for (int i = 0; i < 3; i++)
{
grid.ColumnDefinitions.Add(new ColumnDefinition());
grid.RowDefinitions.Add(new RowDefinition());
}
// 创建9个按钮
for (int x = 0; x < 3; x++)
for (int y = 0; y < 3; y++)
{
Button btn = new Button();
btn.Content = "第" + (y + 1) + "行 第" + (x + 1) + "列";
btn.Margin = new Thickness(10);
grid.Children.Add(btn);
Grid.SetRow(btn, y);
Grid.SetColumn(btn, x);
}
// 创建splitter,指派其位置。此处位于第2行第2列处
GridSplitter split = new GridSplitter();
split.Width = 2;
split.Background = Brushes.Green;
grid.Children.Add(split);
Grid.SetRow(split, 1);
Grid.SetColumn(split, 1);
}
}
}
运行后,在第2行第2列后会出现一条绿色的线,移动它时,不同行的列的宽度也会跟着改变。
运行结果如下:
第07个小程序:分隔客户区(SplitTheClient.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
namespace Chapter06
{
class SplitTheClient : Window
{
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new SplitTheClient());
}
public SplitTheClient()
{
Title = "分隔客户区";
Height = 288;
Width = 480;
WindowStartupLocation = WindowStartupLocation.CenterScreen;
// 具有垂直splitter的Grid
// 单行,无需设置row
// 3列:第1列放按钮1,第2列放垂直splitter,第3列放grid2
Grid grid1 = new Grid();
grid1.ColumnDefinitions.Add(new ColumnDefinition());
grid1.ColumnDefinitions.Add(new ColumnDefinition());
grid1.ColumnDefinitions.Add(new ColumnDefinition());
grid1.ColumnDefinitions[1].Width = GridLength.Auto;
Content = grid1;
// 垂直splitter左边的Button
Button btn = new Button();
btn.Content = "按钮1";
grid1.Children.Add(btn);
Grid.SetRow(btn, 0);
Grid.SetColumn(btn, 0);
// 垂直splitter.
GridSplitter split = new GridSplitter();
split.ShowsPreview = true;
split.Background = Brushes.Blue;
split.HorizontalAlignment = HorizontalAlignment.Center;
split.VerticalAlignment = VerticalAlignment.Stretch;
split.Width = 6;
grid1.Children.Add(split);
Grid.SetRow(split, 0);
Grid.SetColumn(split, 1);
// 具有水平splitter的Grid
// 3行:第1行放按钮2,第2行放水平splitter,第3行放按钮3
// 单列,无需设置column
Grid grid2 = new Grid();
grid2.RowDefinitions.Add(new RowDefinition());
grid2.RowDefinitions.Add(new RowDefinition());
grid2.RowDefinitions.Add(new RowDefinition());
grid2.RowDefinitions[1].Height = GridLength.Auto;
grid1.Children.Add(grid2);
Grid.SetRow(grid2, 0);
Grid.SetColumn(grid2, 2);
// 水平splitter上方的Button
btn = new Button();
btn.Content = "按钮2";
grid2.Children.Add(btn);
Grid.SetRow(btn, 0);
Grid.SetColumn(btn, 0);
// 水平splitter.
split = new GridSplitter();
split.ShowsPreview = true;
split.Background = Brushes.Blue;
split.HorizontalAlignment = HorizontalAlignment.Stretch;
split.VerticalAlignment = VerticalAlignment.Center;
split.Height = 6;
grid2.Children.Add(split);
Grid.SetRow(split, 1);
Grid.SetColumn(split, 0);
// 水平splitter底部的Button
btn = new Button();
btn.Content = "按钮3";
grid2.Children.Add(btn);
Grid.SetRow(btn, 2);
Grid.SetColumn(btn, 0);
}
}
}
运行结果:
第08个小程序:颜色卷轴(ColorScroll.cs)
using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;
namespace Chapter06
{
class ColorScroll : Window
{
ScrollBar[] scrolls = new ScrollBar[3];
TextBlock[] txtValue = new TextBlock[3];
Panel pnlColor;
[STAThread]
public static void Main()
{
Application app = new Application();
app.Run(new ColorScroll());
}
public ColorScroll()
{
Title = "颜色卷轴";
Width = 500;
Height = 300;
WindowStartupLocation = WindowStartupLocation.CenterScreen;
// 包含垂直splitter的GridMain
Grid gridMain = new Grid();
//gridMain.ShowGridLines = true;
Content = gridMain;
// GridMain的列定义
// 3列:第1列放grid,第2列放垂直splitter,第3列放颜色面板pnlColor
ColumnDefinition coldef = new ColumnDefinition();
coldef.Width = new GridLength(200, GridUnitType.Pixel);
gridMain.ColumnDefinitions.Add(coldef);
coldef = new ColumnDefinition();
coldef.Width = GridLength.Auto;
gridMain.ColumnDefinitions.Add(coldef);
coldef = new ColumnDefinition();
coldef.Width = new GridLength(100, GridUnitType.Star);
gridMain.ColumnDefinitions.Add(coldef);
// 垂直splitter
GridSplitter split = new GridSplitter();
split.HorizontalAlignment = HorizontalAlignment.Center;
split.VerticalAlignment = VerticalAlignment.Stretch;
split.Width = 6;
gridMain.Children.Add(split);
Grid.SetRow(split, 0);
Grid.SetColumn(split, 1);
// splitter右边的面板,用来显示颜色
pnlColor = new StackPanel();
pnlColor.Background = new SolidColorBrush(SystemColors.WindowColor);
gridMain.Children.Add(pnlColor);
Grid.SetRow(pnlColor, 0);
Grid.SetColumn(pnlColor, 2);
// 左边的第2个Grid,将其加入gridMain
Grid grid = new Grid();
//grid.ShowGridLines = true;
gridMain.Children.Add(grid);
Grid.SetRow(grid, 0);
Grid.SetColumn(grid, 0);
// 定义3行,分别放置label,scroll和label
RowDefinition rowdef = new RowDefinition();
rowdef.Height = GridLength.Auto;
grid.RowDefinitions.Add(rowdef);
rowdef = new RowDefinition();
rowdef.Height = new GridLength(100, GridUnitType.Star);
grid.RowDefinitions.Add(rowdef);
rowdef = new RowDefinition();
rowdef.Height = GridLength.Auto;
grid.RowDefinitions.Add(rowdef);
// 3列:红、绿、蓝
for (int i = 0; i < 3; i++)
{
coldef = new ColumnDefinition();
coldef.Width = new GridLength(33, GridUnitType.Star);
grid.ColumnDefinitions.Add(coldef);
}
for (int i = 0; i < 3; i++)
{
Label lbl = new Label();
lbl.Content = new string[] { "红", "绿", "蓝" }[i];
lbl.HorizontalAlignment = HorizontalAlignment.Center;
grid.Children.Add(lbl);
Grid.SetRow(lbl, 0);
Grid.SetColumn(lbl, i);
scrolls[i] = new ScrollBar();
scrolls[i].Focusable = true;
scrolls[i].Orientation = Orientation.Vertical;
scrolls[i].Minimum = 0;
scrolls[i].Maximum = 255;
scrolls[i].SmallChange = 1;
scrolls[i].LargeChange = 16;
scrolls[i].ValueChanged += ScrollOnValueChanged;
grid.Children.Add(scrolls[i]);
Grid.SetRow(scrolls[i], 1);
Grid.SetColumn(scrolls[i], i);
txtValue[i] = new TextBlock();
txtValue[i].TextAlignment = TextAlignment.Center;
txtValue[i].HorizontalAlignment = HorizontalAlignment.Center;
txtValue[i].Margin = new Thickness(5);
grid.Children.Add(txtValue[i]);
Grid.SetRow(txtValue[i], 2);
Grid.SetColumn(txtValue[i], i);
}
// 初始化卷轴
Color clr = (pnlColor.Background as SolidColorBrush).Color;
scrolls[0].Value = clr.R;
scrolls[1].Value = clr.G;
scrolls[2].Value = clr.B;
// 设置初始焦点
scrolls[0].Focus();
}
void ScrollOnValueChanged(object sender, RoutedEventArgs args)
{
ScrollBar scroll = sender as ScrollBar;
Panel pnl = scroll.Parent as Panel;
TextBlock txt = pnl.Children[1 +
pnl.Children.IndexOf(scroll)] as TextBlock;
txt.Text = String.Format("{0}/n0x{0:X2}", (int)scroll.Value); //RGB和16进制显示
pnlColor.Background =
new SolidColorBrush(
Color.FromRgb((byte)scrolls[0].Value,
(byte)scrolls[1].Value, (byte)scrolls[2].Value));
}
}
}
ScrollOnValueChanged事件处理器负责将ScroolBar的值更新到TextBlock,然后根据这3个滚动条的值计算出一个新的Color,显示在Color面板。
运行效果:
相关文章推荐
- WPF学习总结和记录(九)-Grid仿VS的界面
- WPF学习总结和记录(二)内容控件
- WPF学习总结和记录(三)Items控件上
- devDevexpress.XtraGrid.GridControl.GridView 学习记录
- 新手学习wpf记录 button下篇 等级5
- WPF 学习记录——Application
- (WPF学习记录)第十三章 ListBox选取
- wpf学习笔记(4)《都是自己根据网络资源学习记录的仅供参考》
- (WPF学习记录)第九章 Routed输入事件
- WPF 学习记录(乱七八糟的小问题)
- 新手学习wpf记录 button上篇 等级3
- WPF-Grid学习
- (WPF学习记录)第三章 Content的概念
- (WPF学习记录)第四章 按钮与其他控件
- WPF学习记录2_XAML
- WPF学习总结和记录(五)-Menu
- WPF学习总结和记录(六)-文本和墨水
- (WPF学习记录)第七章 Canvas
- WPF 学习记录——Window
- WPF-学习笔记 将控件添加到Grid中的指定行指定列