• WPF教程尝试(修正部分格式)


    抱歉,格式还是不够顺眼,从word复制过来,格式有了一些变化,虽然用Live Writer重排,但实在是麻烦。改天,我放Word附件上来。^_^

    另外,请各位指点,教程怎样写,读者会更有兴趣。

    01. 创建软件雏形

    这个雏形包括4个项目(Project):

    1. 一个主程序(WPF Application)项目,命名为:DataTracer
    2. 一个组件库(WPF User Control Library)项目,命名为:K3UcLib
    3. 一个控件库(WPF Custom Control Library)项目,命名为:K3CcLib
    4. 一个算法库(Class Library)项目,命名为:K3Helper

    作为入门,这看起来有点复杂,不过实现起来还算简单。

    菜单:File > New > Project…

     

    clip_image001

    clip_image003

    菜单:File > Add > New Project…

    clip_image005

    clip_image007

    clip_image009

    THINKING:

    通常,复杂是由简单构成的,只要我们合理的分解它;
    复杂的设计,并不意味着复杂的实现;同样,简单的设计,也不意味着简单的实现;
    不过,没有准备迎接复杂挑战的简单设计,却通常是小小噩梦的开始。

    F5 运行,看看结果!

    02. 制作一个组件

    我习惯将User Control称为组件,将Custom Control称为控件。

    他们的区分,简单说:User Control通常通过组合多个控件产生,Custom Control通常通过扩展单个控件产生。

    现在,我们先制作一个准备用来替换现有窗口标题的组件,命名为:K3WindowHeader。

    Project à Add User Control,然后修改XAML,并编译(Shift F6)

     

    <Border CornerRadius="0, 0, 10, 10" Background="DarkBlue">

    <DockPanel LastChildFill="True">

    <Button Content="关闭" Width="75" Height="23" DockPanel.Dock="Right" />

    <TextBlock Text="Window Header" DockPanel.Dock="Left" Foreground="White"/>

    </DockPanel>

    </Border>

    这个组件包括两个控件Button,TextBlock。

    CornerRadius用于设定Border四个角的弧度

    = ”LeftTop, RightTop, RightBottom, LeftBottom”

    DockPanel.LastChildFill,很有用的属性。

    注意DockPanel所包含组件的顺序,并在组件中正确的使用DockPanel.Dock属性。

    在DataTracer中使用这个组件。

    Project à Add References,添加K3UcLib,然后修改MainWindow.XAML:

     

    <Window …

    xmlns:K3UcLib="clr-namespace:K3UcLib;assembly=K3UcLib"

    WindowStyle="None"

    >

    <Grid>

    <Grid.RowDefinitions>

    <RowDefinition Height="Auto"/>

    <RowDefinition Height="*"/>

    <RowDefinition Height="Auto"/>

    </Grid.RowDefinitions>

    <K3UcLib:K3WindowHeader Height="25" />

    </Grid>

    将WindowStyle设为None,将窗口标题隐掉,从而为DIY新的窗口标题做好准备。

    Height, Width可取值包括:

    Auto(自适应),*(全部剩余),NaN(相当于Auto),数值

    F5 à 运行,看看结果!

    这个窗口怎么关掉?Alt + F4!

    这个窗口好丑!别着急,如果你真的很急,可以先试着使用 Margin属性及xxxAlignment属性,调整一下位置(试一试我的调整,如下)。

     

    <Border CornerRadius="0, 0, 10, 10" Background="DarkBlue" Margin="3,0,3,0">

    <DockPanel LastChildFill="True">

    <Button Content="关闭" Width="75" Height="23" DockPanel.Dock="Right" Margin="0, 0, 10, 0" HorizontalAlignment="Center" VerticalAlignment="Center" />

    <TextBlock Text="Window Header" DockPanel.Dock="Left" Foreground="White" HorizontalAlignment="Center" VerticalAlignment="Center" />

    </DockPanel>

    </Border>

    F5 à 运行,看看结果!

     

    03. 添加事件,关闭窗口

    需求:当用户点击“关闭”按钮时,关闭主窗口。

    实现:为“关闭”按钮添加Click事件处理。有两种实现方式:

    (1) 通过XAML文件中实现:<Button Name=”buttonClose” Content=”” …… Click=”buttonClose_Click” …… />

    (2) 通过后台代码实现:this.buttonClose.Click += new new RoutedEventHandler(buttonClose_Click);

    这里,我们采用后者,即后台代码方式,完整代码如下:

     

    public K3WindowHeader() {

    InitializeComponent();

    this.Init();

    }

    void Init() {

    this.buttonClose.Click += new RoutedEventHandler(Button_Click);

    }

    void Button_Click(object sender, RoutedEventArgs e) {

    throw new NotImplementedException();

    }

    注:

    使用Init()方法,是为了使代码整洁。

    在你键入“+=”时,系统将为你自动生成事件代码。你可以先修改所生成的事件处理方法的名字,然后再按“TAB”键,这样就可以生成你想要的名字的方法。在这里,我将默认的buttonClose_click改为Button_Click。

    接下来,我们添加事件处理的内容,以实现关闭主窗体。

    注意,因为我们使用的是另一个组件项目中的组件,而非主程序自身项目中的组件,所以实现起来稍微有点麻烦,不是简单的一个Close()就可以完成。

    在这种情况下,有多重实现方式:

    (1) 假定组件自身知道自己是如何被使用的,如本案例中,它被放在主窗体的Grid中,那么可以这样实现:

     

    ((this.Parent as Grid).Parent as Window).Close();

    这种实现方式,属于hard code,使组件失去了灵活性,不是一个好方法,但它是一个思路,即:只要你能找到你想要的,你就可以做你想做的。

    (2) 将点击“关闭”按钮事件,转化成一个新的事件,告诉引用这个组件的窗体:有人请求关掉你!这个设计有点麻烦,但使组件具有了组件该有的特性:灵活性,或称为适应性,以保证你可以相对随意的使用它。

     

    #region >>>>> 自定义事件 ...

    public static readonly RoutedEvent PreviewWindowHeaderEvent;

    public event RoutedEventHandler PreviewWindowHeaderEventHandler {

    add { this.AddHandler(PreviewWindowHeaderEvent, value); }

    remove { this.RemoveHandler(PreviewWindowHeaderEvent, value); }

    }

    static K3WindowHeader() {

    PreviewWindowHeaderEvent = EventManager.RegisterRoutedEvent(

    "PreviewWindowHeaderEventHandler",

    RoutingStrategy.Tunnel,

    typeof(RoutedEventHandler),

    typeof(K3WindowHeader));

    }

    #endregion

    ……

    void Button_Click(object sender, RoutedEventArgs e) {

    RoutedEventArgs eventArgs = new RoutedEventArgs();

    eventArgs.RoutedEvent = PreviewWindowHeaderEvent;

    RaiseEvent(eventArgs);

    }

    这段代码,加在K3WindowHeader中。

    #region #endregion的合理使用,有利于提升代码的可读性。你可以加上注释。BTW,我添加>>>>> … 是为了美观,读者可以试试去掉它,或改变它,看看你自己更喜欢哪一个。

    注意,我添加了static 类型的构造函数,以便注册自定义事件。

    Event有两种类型,其关键参数是:RoutingStrategy,其取值的不同,将生成两种传递方向不同事件。详述如下:

         
     

    public static readonly RoutedEvent PreviewWindowHeaderEvent;

    public event RoutedEventHandler PreviewWindowHeaderEventHandler {

    add { this.AddHandler(PreviewWindowHeaderEvent, value); }

    remove { this.RemoveHandler(PreviewWindowHeaderEvent, value); }

    }

    static MainWindow() {

    PreviewWindowHeaderEvent = K3WindowHeader.PreviewWindowHeaderEvent.AddOwner(typeof(MainWindow));

    }

    void Init() {

    this.PreviewWindowHeaderEventHandler += new RoutedEventHandler(CustomEventHandler);

    }

    void CustomEventHandler(object sender, RoutedEventArgs e) {

    this.Close();

    }

    这段代码,加在DataTracer中。

    注意这段代码与上段代码的不同,在于静态构造中,我们通过事件的AddOwner方法,将这两个自定义事件关联起来,从而保证了可以捕获到该事件。

    同样,我使用了Init来使代码整洁,并在其中添加了对该特定事件的处理程序。别忘了将Init()放入构造函数中。

    F5 à 运行,看看结果!

  • 相关阅读:
    Ionic2 开发笔记(1)ionic2 +angular2搭建
    git随笔(常用命令归纳)
    Ionic2开发笔记(2)创建子页面及其应用
    移动开发规范
    OnsenUI和AngularJS配合搭建混合应用基本步骤(Cordova安装与创建平台项目等)(一)
    解决Andriod软键盘出现把原来的布局给顶上去的方法(转)
    Android BroadCast 基础知识
    Andriod Service 基础知识
    Android--双击退出程序
    Android---自动启动方法
  • 原文地址:https://www.cnblogs.com/KingWorld/p/2317683.html
Copyright © 2020-2023  润新知