程序效果

最终得到程序的运行效果如图。拖动Slider可以使按钮的背景色出现相应变化。

需求分析和架构设计

如果是你,接到了这样的一个程序设计要求,会怎样思考?
第一步当然是需求分析啦。这个程序相对简单,需要分析的主要是各个控件之间的数据联系。这主要体现在Slider, Textbox和Button间的同步关系上:
拖动Slider的滑块,要求TextBox里的数值也要变化,同时Button的背景色也要发生相应变化。改变TextBox里的值,滑块的位置和Button的背景也要做相应调整。
一个习惯于WinForm的同学就会有很自然的想法——处理消息(.NET表现为事件)呗。对Slider滑块的滑动这个事件,设置一个EventHandler,以更新Textbox的Text属性和Button的Background属性。对于Textbox.Text的更改这个事件,设置一个EventHandler,更新Slider的Value属性和Button的Background属性。
很好。下面我们就来看一下在WPF中,思维可以变得如此不同而简单。

实现过程

第一步自然是创建工程。首先在Visual Studio 2008下,新建一个工程,选择Visual C#里面的WPF Application即可。

稍等片刻就可以看见一个工程被创建,同时默认的窗体设计文件Windows1.xaml被显示出来了。注意虽然XAML中可以像MFC那样用图形化的方式放置控件,但是由于XAML的功能太强大,图形化界面很难完全表达,因此在目前的版本中主要还是采用代码的方式进行界面设计。不过微软已经放风说在Visual Studio 2010中这样的情况会加以改善。
第二步是设计UI。首先在XAML代码中<Grid></Grid>间插入:


        <Grid.RowDefinitions>
<RowDefinition /> <RowDefinition />
<RowDefinition /> <RowDefinition />
<RowDefinition /> </Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="50" />
</Grid.ColumnDefinitions>

这一段代码主要是将整个界面唰唰切成5行3列一共15个大块,在设计界面中可以很清楚的看到(如下图)。其中最左边和最右边这两列固定为50像素,中间那一列是宽度可变的。

下面就要往里面放控件了。在</Grid.ColumnDefinitions>和</Grid>间继续加入以下代码:

        <TextBlock Grid.Column="0" Grid.Row="0">Red</TextBlock>         <Slider Grid.Column="1" Grid.Row="0"/>         <TextBox Grid.Column="2" Grid.Row="0"/>

这是在第一行的第一个格子里放了一个TextBlock控件,用来显示那个Red。然后在同一行的第二个格子里放了一个Slider,第三个格子里放了一个TextBox。现在设计界面是这样的:

看起来好丑哦。没关系我们来修饰一下。
首先窗口太大了,把XAML文件中第四行中Window1的Height改成200先。然后每个控件把格子占得满满的,影响美观。在各个控件中加入Margin="5",比如Slider控件的代码现在看起来应该是这样的:
<Slider Grid.Column="1" Grid.Row="0" Margin="5"/>
这样就使得空间和格子间有一定的间距,看起来舒服一点。
然后将各个控件的垂直对齐方式设为中间对齐,加入VerticalAlignment="Center"即可。好的,现在蛮漂亮的了。

代码看起来应该是这样:

        <TextBlock Grid.Column="0" Grid.Row="0" Margin="5" VerticalAlignment="Center">Red</TextBlock>
<Slider Grid.Column="1" Grid.Row="0" Margin="5" VerticalAlignment="Center"/>
<TextBox Grid.Column="2" Grid.Row="0" Margin="5" VerticalAlignment="Center"/>

下面我们来加入其余三个TextBlock, Slider和TextBox。分别代表Green, Blue, Alpha值。将以上代码复制粘贴三份即可。注意每一行都要相应修改Grid.Row值。第二行为1,以此类推。不要忘了把后面几行TextBlock里的Red改成相应的Green, Blue等等哦。现在界面看起来像这样:

最后需要在最后一行加入一个Button。在</Grid>前添加如下代码:

        <Button Grid.Column="0" Grid.ColumnSpan="3" Grid.Row="4"                      HorizontalAlignment="Center" Width="100"  Margin="5">             <Rectangle Width="10" Height="10" Fill="Red"/>         </Button>

很容易看懂这是说要添加一个宽度100像素,水平中央对齐,在第5行的按钮。按钮的内容是一个长宽各为10,红色的方形。只是要注意Grid.ColumnSpan="3"表示这一个控件将占用3列的空间。

再把Window1的Title改成ColorChange。至此UI的设计就结束了。如下图。

呼,界面设计说起来还是比较繁琐的。终于进入WPF强大的地方了。首先是界面设计的时候注意到了吗?Button的内容可以是一个方块诶!如果我告诉你还能是其他控件比如是一个slider外加一个TextBox呢?就像这样:

要是在MFC里面还不要搞死人。最简单的情况是通过改CButton的bitmap来实现在按钮上显示图片。就算只想在里面嵌入一个Slider,就首先要继承CButton类,然后广大人民充分发挥聪明才智吧,拼死拼活总算搞出来一种控件叫做CSliderButton。然后一拍脑袋,哎呀我搞错了,其实我想嵌入一个TextBox的。好吧,大返工……但是在WPF里如此简单,我们要做的仅仅是把<Rectangle />换成其他控件就好了,比如<Slider />,或者另一个有复杂结构的<Grid>。是不是很神奇?
还有我们上面进行的UI设计相对MFC来说繁琐很多,但是也要强大很多。这主要表现在窗口的大小被改变时。一个MFC对话框程序,如果没有经过特别精心的设计的话,一旦窗口大小被拖动或者最大化,一坨控件还像原来一样分布,拥堵在左上角,唉……但是上面设计出的WPF的程序就不会,控件仍然会均匀分布在窗口中。(你可以自己试试看,如果觉得还是不够完美可以自己想想怎样再改动呢?)

下面进入消息处理阶段了,如果还可以这样称呼的话。第一步要把Slider和TextBox中的内容关联起来。为了以下程序设计的方便,我们必须要先给各个控件起个名字。在第一行的Slider里面添加Name属性,叫它ColorSliderR好了!也就是说,在<Slider ... />中加入Name="ColorSliderR"
同样的,我们给剩下各个slider起名叫做ColorSliderG/B/A。把那个Button称作MainButton。
然后要调整Slider的属性,否则没有应用价值。在各个Slider的代码里加入Maximum="255" Minimum="0" Value="255"。这表示滑块到达最右边的时候表示255,最左边表示0,初始值在255。那么Slider的代码看起来应该是这样的:

        <Slider Grid.Column="1" Grid.Row="0" Margin="5" VerticalAlignment="Center" Maximum="255" Minimum="0" Value="255" Name="ColorSliderR"/>

睁大眼睛啦!WPF神奇的地方又来啦!什么消息处理,这么麻烦,走开!不就是同步嘛,把TextBox和Slider绑上不就得了。好的。在4个<TextBox ... />中加入代码Text="{Binding Path=Value, ElementName=ColorSliderR}",注意ElementName的值要根据各个控件改动哦。这样就把两个控件Bind起来了。运行一下看看:

成功啦!简单不?啧啧,还带小数点的,真牛X。注意,如果想要通过改变文本框的内容来改变滑块位置的话,需要在输入完毕后切换一下焦点,也就是随便点一下本窗口内的其他地方改动才会生效。
真么快?都到第四步了。下面就要改变背景色啦。XAML固然强大,但光玩控件间的绑定没意思,咱辛辛苦苦学的for啊while啊不都没用了嘛。这下咱换种方式。把XAML和后台代码绑定起来。
为了实现这个目标,先要做一个桥梁——在XAML和后台代码间沟通的桥梁。终于轮到C#上场了,人家都急死了。右击XAML设计界面,单击打开Window1.xaml.cs。啊,终于看到熟悉的using了,激动死了激动死了。
在public partial class Window1这个类的后面,也就是这个类的}的后面,相当于跟这个类并列的地位,不要搞错了啊,插入一个类,代码如下:


public class SliderCommunicator: INotifyPropertyChanged
{ // INotifyPropertyChanged Members
  public event PropertyChangedEventHandler PropertyChanged;
  protected void Notify(string propName)
  {
    if (this.PropertyChanged != null)
    {
     PropertyChanged(this, new PropertyChangedEventArgs(propName));
    }
  }
  int sliderValue = 255;
  public int SliderValue
  {
    get { return sliderValue; }
    set {
        sliderValue = value;
        Notify("SliderValue");
       }
      }
   }

学过C#的对这个应该很熟悉,标准的事件处理方法。大意就是这个类里面有一个属性SliderValue。它一旦被更改了就会大叫:老大我被人动啦!然后——当然很多人根本不睬他,只有他的老大听到了就会过来看看并作出相关操作。这是C#针对消息处理作出的语言内部的支持。

还有,不要忘了在最前面那一坨using的最后插入一句

using System.ComponentModel;

这是为了提供对事件处理的支持。

有了这个类,桥架起来了,绑定就好办了。当然一个控件应该是和代码中的一个对象绑定而不是和一个类绑定,所以叫你有面向对象程序设计基础呢,否则对象啊类啊还不把你绕昏掉。对象自然只能在Window1类中定义。好的,在类中(具体位置随便在哪,只要这个类里面就好)加入

        SliderCommunicator sliderCR, sliderCG, sliderCB, sliderCA;

然后搞个函数把他们初始化一下,整个Window1类看起来应该是这样的:


 public partial class Window1 : Window
{
  SliderCommunicator sliderCR, sliderCG, sliderCB, sliderCA;
  public Window1()
  {
    InitializeComponent();
  }
  void InitDataBinding()
  {
    sliderCR = new SliderCommunicator();
    sliderCG = new SliderCommunicator();
    sliderCB = new SliderCommunicator();
    sliderCA = new SliderCommunicator();
  }
}

嗯嗯,很好,下面我们就可以把XAML和C#绑起来了。两步走,第一步,改改InitDataBinding函数,改成这样:


void InitDataBinding()
{
  sliderCR = new SliderCommunicator();
  ColorSliderR.DataContext = sliderCR;
  sliderCG = new SliderCommunicator();
  ColorSliderG.DataContext = sliderCG;
  sliderCB = new SliderCommunicator();
  ColorSliderB.DataContext = sliderCB;
  sliderCA = new SliderCommunicator();
  ColorSliderA.DataContext = sliderCA;
}

意思就是把每个Slider控件和相应的对象绑起来。

第二步,回到XAML设计界面,在每一个<Slider ... />里把原来的Value="255"改成Value="{Binding Path=SliderValue}"
这是更进一步具体地说,把这个Slider的Value属性和相应的那个对象的SliderValue绑定起来。
好吧现在看看发生了什么事情呢。当Slider的滑块一被拖动的时候,WPF就会自动更新绑在一起的SliderCommunicator对象的Value属性,然后它就会大叫起来老大我被人动啦!但是现在还没人理他呀,没用呢。没关系,我们给他造出一个老大来。
首先在Window1中定义函数


        void ChangeMainButtonColor(object sender, PropertyChangedEventArgs e)
{
  SolidColorBrush NewColor = new SolidColorBrush();
  NewColor.Color = Color.FromArgb((byte)sliderCA.SliderValue, (byte)sliderCR.SliderValue, (byte)sliderCG.SliderValue, (byte)sliderCB.SliderValue);
  MainButton.Background = NewColor;
}

还记得那个Button其实叫做MainButton吗?这个函数就是改变Button背景值的。下面让它做个实实在在的老大。

在InitDataBinding的最后部分加入语句


            sliderCR.PropertyChanged += new PropertyChangedEventHandler(ChangeMainButtonColor);
sliderCG.PropertyChanged += new PropertyChangedEventHandler(ChangeMainButtonColor);
sliderCB.PropertyChanged += new PropertyChangedEventHandler(ChangeMainButtonColor);
sliderCA.PropertyChanged += new PropertyChangedEventHandler(ChangeMainButtonColor);

好了。现在SliderCommunicator一叫Button就会跑过来,然后把自己的背景改掉了。大功告成!运行看看:

[WPF]设置背景色的更多相关文章

  1. WPF设置DataGrid行内容高度自适应 与 TextBox/TextBlock内容高度自适应

    WPF设置DataGrid行内容高度自适应  TextBox/TextBlock内容高度自适应  参考: DataGrid 控件中的调整大小选项: http://msdn.microsoft.com/ ...

  2. listview当选中某一个item时设置背景色其他的不变

    listview当选中某一个item时设置背景色其他的不变: 可以使用listview.setOnFoucsChangeListener(listener) ; /** * listview获得焦点和 ...

  3. java 解决JFrame不能设置背景色的问题 分类: Java Game 2014-08-15 09:48 119人阅读 评论(0) 收藏

    这段时间比较多,于是写一写JAVA的一些IT技术文章.如有JAVA高手请加QQ:314783246,互相讨论. 在Java的GUI设计中,Frame和JFrame两者之间有很大差别,上次刚学时编一个窗 ...

  4. QLCDNumber设置背景色和显示数字颜色

          只看楼主 倒序阅读楼主  发表于: 2013-10-22          //LCD时间显示    QLCDNumber *m_pLcdTime = new QLCDNumber(thi ...

  5. MFC 可以设置背景色、字体、字体颜色、透明背景的 Static 静态文本控件

    MFC库里没有符合这个条件的控件,于是我自己写了一个,初步测试有效. 注:可以设置透明背景,但还不能做到透明度设置(如50%透明度) 如果设置了背景色,就不保留透明背景 默认背景色是透明的 [cpp] ...

  6. WPF设置VistualBrush的Visual属性制作图片放大镜效果

    原文:WPF设置VistualBrush的Visual属性制作图片放大镜效果 效果图片:原理:设置VistualBrush的Visual属性,利用它的Viewbox属性进行缩放. XAML代码:// ...

  7. 如何 Graphics 对象设置背景色

    用 Clear 方法可以轻松地给 Graphics 对象设置背景色. using (Bitmap bmp = new Bitmap(width, height)){    using (Graphic ...

  8. ASP.Net ListBox DropdownList 不同条目设置背景色和字体颜色( 转· 载 )

    ASP.Net ListBox DropdownList 不同条目设置背景色和字体颜色 2009-09-30  来自:真有意思 [ZU14.CN]  字体大小:[大 中 小] 摘要:在HTML展现页面 ...

  9. WPF设置全局字体和字体嵌入

    原文:WPF设置全局字体和字体嵌入 版权声明:本文为博主原创文章,未经博主允许不得转载. https://blog.csdn.net/CLeopard/article/details/40590373 ...

随机推荐

  1. [vivado系列]Zynq开发常用文档

    时间:2016.06.13 目的:阶段性总结学习的策略 ------------------------------------------------------------------------ ...

  2. 316. Remove Duplicate Letters

    Given a string which contains only lowercase letters, remove duplicate letters so that every letter ...

  3. mysql 允许远程访问

    原来装mysql数据库的时候就想,这个只要在本地访问就可以了,没有必要让远程访问.可是,今天想把数据放到远程的机器上,却发现,不是简单的将sql语句(指导出的语句)执行一遍就行了,对于那些自增的字段, ...

  4. 简单的block

    int multi = 7;                int (^myBlock)(int) = ^(int num){            return num * multi;       ...

  5. Java 名词

    Plain Ordinary Java Object    pojo  简单java对象 Constant   常量 Business Object   BO  业务对象 Framework  框架

  6. IOS系列swift语言之课时八

    这节课需要讲的就是可选链,内存管理,引用计数,unowned解决 //: Playground - noun: a place where people can play import UIKit / ...

  7. $.grep(array, callback, [invert])过滤,常用

    $.grep(array, callback, [invert])过滤,常用 解释: 使用过滤函数过滤数组元素.此函数至少传递两个参数(第三个参数为true或false,对过滤函数返回值取反,个人觉得 ...

  8. Camtasia Studio屏幕录像安装与破解

    Camtasia Studio汉化版是一款功能强大的屏幕录像工具,能在任何颜色模式下轻松地记录屏幕动作,包括影像.音效.鼠标移动轨迹.解说声音等.Camtasia Studio具有强大的视频播放和视频 ...

  9. [转载] python 计算字符串长度

    本文转载自: http://www.sharejs.com/codes/python/4843 python 计算字符串长度,一个中文算两个字符,先转换成utf8,然后通过计算utf8的长度和len函 ...

  10. python之路——基础篇(2)模块

    模块:os.sys.time.logging.json/pickle.hashlib.random.re 模块分为三种: 自定义模块 第三方模块 内置模块 自定义模块 1.定义模块 将一系列功能函数或 ...