程序效果

最终得到程序的运行效果如图。拖动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. Spark+Hadoop问题小结

    1.spark执行./start-all.sh报"WARN Utils: Service 'sparkWorker' could not bind on port 0. Attempting ...

  2. MySQL_订单类型细分_20161222

    #目前在做一个各城市日订单角度的对比分析,因此需要对订单类型进行一下规整.由于App上产品活动许多,查询了多个表,将订单类型规则进行了统一,优惠券和满减券不能同时使用,创建的这两个表都是以订单ID为k ...

  3. bootstrap 3 with IE8 compatibility

    12栅格布局在IE8下不起作用. 下载并引用html5shiv.js和respond.js 参考: 1.http://nextflow.in.th/en/keep-your-responsive-we ...

  4. 有关emoji表情以及utf-16编码

        昨日IOS组的同事遇到一个棘手的问题:当输入框内含有emoji表情时,如何获取文本框内的字符数(一个emoji表情算一个字符).       先从我最近接触的JAVA说起,JAVA中,在使用S ...

  5. NDO to PNP( ndoutils to PNP4Nagios)

    How to use this script The aim of this script is to import your ndo database directly into PNP4nagio ...

  6. Java Web 环境搭建步骤(超详细,包括前期安装步骤)

    Java Web 环境搭建步骤 安装对应版本的JDK 配置环境变量 本人安装的路径是C盘,在path中加入C:\Program Files\Java\jdk1.8.0_65\bin 测试配置成功,cm ...

  7. 邮件中继成畅邮标配 U-Mail为何领先

    中国力推“一带一路”战略,为首成立“亚投行”,越来越多的中国企业酝酿走出去.在企业间的商务往来中,电子邮件将扮演着重要角色,但是因为要跨洋 过海,各国互联网环境和法律法规有所区别,面临着种种变数,对方 ...

  8. hdu5834

    题目让求得是从任意一点出发可以不回来得到的最大的价值 这应该不算特别水的树形dp了,它不止要从上往下dfs,后来海要重新dfs,根据父亲节点更新儿子节点,算是正常的树形dp中比较简单的吧. 思路: 先 ...

  9. PPTP-VPN第三章——用户流量与并发数限制

    在前面两篇文章中详细介绍了pptp vpn的安装与使用,以及如何配置用户认证存入mysql数据库.本文将在前面两篇文章的基础上介绍如何对用户的流量做限制,同时限制相同账号的用户,同一时刻的在线数为1. ...

  10. Java file read & write

    1. read public static void readfile(String filepath) { BufferedReader br = null; try { String sCurre ...