程序效果

最终得到程序的运行效果如图。拖动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. Request Entity Too Large for Self Hosted ASP.Net Web API在Selfhost的api后台怎么解决Request Entity Too Large问题

    Request Entity Too Large for Self Hosted ASP.Net Web API在Selfhost的api后台怎么解决Request Entity Too Large问 ...

  2. 构建Maven聚合工程

    最近,准备构建一个Maven的项目,基于模块化的结构思想,决定使用Maven的聚合工程进行构建. 环境准备: (1)eclipse 这里推荐使用spring封装的eclipse(即STS) ,STS中 ...

  3. 简单的androidStudio 添加Jar包

    感谢http://blog.csdn.net/ta893115871/article/details/46955791博主的文章, 1新建一个空项目 2在项目下添加一个新的moudle 3在该moud ...

  4. extjs ajax java简单精美验证码实现 有图

    前端:利用ExtJs的autoEl功能加载图片. var imgCheckValid = new Ext.create('Ext.Component',{ width: 70, //图片宽度 heig ...

  5. Parallel线程使用

    Parallel的静态For,ForEach和Invoke方法       在一些常见的编程情形中,使用任务也许会提升性能.为了简化编程,静态类System.Threading.Tasks.Paral ...

  6. Python学习资料下载地址(转)

    [转]Python学习资料和教程pdf 开发工具: Python语言集成开发环境 Wingware WingIDE Professional v3.2.12 Python语言集成开发环境 Wingwa ...

  7. Libevent 的多线程操作

    起因是event_base 跨线程add/remove event 导致崩溃或者死循环. 据查:libvent 1.4.x是非线程安全的,要跨线程执行event_add,会有问题.因此传统做法是通过p ...

  8. jquery的滑动

    (1)slideDown(speed,callback)方法:用于想下滑动的方法. $("#flip").click(function(){ $("#panel" ...

  9. Checkpoints codeforces 709B

    http://codeforces.com/problemset/problem/709/B 题意:给出一条横向坐标轴,给出Vasya所在的坐标位置及其另外n个坐标.Vasya想要至少访问n-1个位置 ...

  10. C# 对Access数据库操作的通用类

    (转载自博主Jerry很简单) //Access数据库-C# 操作类 代码using System;using System.Collections.Generic;using System.Linq ...