zoukankan      html  css  js  c++  java
  • [Silverlight入门系列]使用MVVM模式(6):使用Behavior

    Behavior把一些常用的行为封装成可重复使用的组件(Component)在理想状况下,Designer(设计师)domain expert(特定领域的专家,例如财会人员、HR人员、或MIS)甚至可以完全不需要具备程序设计的观念,只需要了解基础的事件(Event)观念,就可以顺利的开发出一套系统,若需要实现特定的功能时,可商请developere为他们开发所需要的Behaviordesigner只需要取得这些Behavior并使用即可。例如,界面设计人员可以使用Expression Blend把一个Behavior拖到一个界面元素上,比如右键点击以后启动一段动画这个行为,这个界面元素就会自动执行,岂不是很清爽!(当然,执行函数还是要编程人员编写),来个例子:

    界面xaml:

    View Code
    1 <UserControl
    2 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    3 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    4 xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    5 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    6 xmlns:wm="clr-namespace:AsycValidation"
    7 xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" xmlns:ei="http://schemas.microsoft.com/expression/2010/interactions" x:Class="AsycValidation.MainPage"
    8 mc:Ignorable="d"
    9 x:Name="MyUserControl"
    10 d:DesignHeight="300" d:DesignWidth="400">
    11
    12 <Grid x:Name="Layout" >
    13 <TextBlock Height="32" HorizontalAlignment="Left" Margin="41,53,0,0" x:Name="textBlock1" Text="Company:" VerticalAlignment="Top" Width="66" />
    14 <TextBox Height="31" HorizontalAlignment="Left" Margin="120,45,0,0" x:Name="textBox1" Text="{Binding CompanyName, Mode=TwoWay, NotifyOnValidationError=True}" VerticalAlignment="Top" Width="119" />
    15 <TextBox Height="30" HorizontalAlignment="Left" Margin="120,104,0,0" x:Name="textBox2" Text="{Binding CompanyID, Mode=TwoWay, NotifyOnValidationError=True}" VerticalAlignment="Top" Width="119" />
    16 <Button Content="Button" Height="36" HorizontalAlignment="Left" Margin="120,156,0,0" x:Name="button1" VerticalAlignment="Top" Width="81" >
    17 <i:Interaction.Triggers>
    18 <i:EventTrigger EventName="Click">
    19 <ei:CallMethodAction MethodName="button1_Click" TargetObject="{Binding ElementName=MyUserControl}"/>
    20 </i:EventTrigger>
    21 <i:EventTrigger>
    22 <ei:CallMethodAction MethodName="button1_loaded" TargetObject="{Binding ElementName=MyUserControl}"/>
    23 </i:EventTrigger>
    24 </i:Interaction.Triggers>
    25 </Button>
    26 </Grid>
    27  </UserControl>

    界面xaml.cs:

    View Code
    1 using System;
    2  using System.Collections.Generic;
    3  using System.Linq;
    4  using System.Net;
    5  using System.Windows;
    6  using System.Windows.Controls;
    7 using System.Windows.Documents;
    8 using System.Windows.Input;
    9 using System.Windows.Media;
    10 using System.Windows.Media.Animation;
    11 using System.Windows.Shapes;
    12
    13 namespace AsycValidation
    14 {
    15 public partial class MainPage : UserControl
    16 {
    17 public MainPage()
    18 {
    19 InitializeComponent();
    20
    21 CompanyModel m1 = new CompanyModel() { CompanyID = 1, CompanyName = "abc" };
    22
    23 companyViewModel = new CompanyViewModel(m1);
    24 this.DataContext = companyViewModel;
    25
    26 }
    27
    28 public void button1_Click()
    29 {
    30 MessageBox.Show("ok");
    31 }
    32
    33 public void button1_loaded()
    34 {
    35 MessageBox.Show("loaded");
    36
    37 }
    38
    39 public CompanyViewModel companyViewModel { get; set; }
    40
    41 }
    42 }

    注意给这个button定义了两个CallMethodAction的behavior:一个是点击事件,一个是加载Loaded事件。

    1 <Button Content="Button" Height="36" HorizontalAlignment="Left" Margin="120,156,0,0" x:Name="button1" VerticalAlignment="Top" Width="81" >
    2 <i:Interaction.Triggers>
    3 <i:EventTrigger EventName="Click">
    4 <ei:CallMethodAction MethodName="button1_Click" TargetObject="{Binding ElementName=MyUserControl}"/>
    5 </i:EventTrigger>
    6 <i:EventTrigger>
    7 <ei:CallMethodAction MethodName="button1_loaded" TargetObject="{Binding ElementName=MyUserControl}"/>
    8 </i:EventTrigger>
    9 </i:Interaction.Triggers>
    10 </Button>

    实现步骤:在VS2010中右键点击xaml文件“在Expression Blend中打开...”,然后左边拖一个Behavior到控件上来,配置属性,保存即可。要注意的是TargetObject属性配置。

    Behavior or Command?

    commandsandbehavior

    MVVM设计模式为了实现UI元素也UI界面逻辑分离项目组决定使用MVVM设计模式。把界面逻辑写在ViewModel层,View层由美工设计,通过绑定VM层的数据,实现分离。可是问题出来了,UI元素如何触发VM层的事件呢? 最开始很多人建议使用command命令,因为silverlight/wpf的很多控件都提供了Command属性。感觉还挺好使,只需要绑定VM层的ICommand属性就可以了。可是后来问题越来越复杂,主要出来以下几方面的问题:

      (1) 只有ButtonBase提供了Command属性。其他没有继承这个基类的元素不提供此接口。需要自己扩展。

      (2) UI元素事件一般会有很多,比如左击、右击、拖拉、load、unload等。

      (3) UI元素可能在初始化时就会需要一些操作,比如Load事件。

     

    开始我们使用Prism提供的DelegateCommandCompositeCommand类来处理,可是对于左、右击这种情况很棘手,重写ICommand,那么多UI元素想累死啊,终于在微软Expression blend中找到答案。使用behavior,一切搞定。

     

    Behavior提供CallMethodAction、ChangePropertyAction、DataStateBehavior等十三个行为,足够你处理一般事件调用情况了。比如CallMethodAction:提供EventName、MethodName两个属性,EventName:你可以选择任意元素事件,MethodName:可以让你直接绑定方法,基本上可以解决所有问题。使用也很简单,只需要在Blend中把相关行为Behavior拖放到控件上,然后设置相关属性,一切OK!

    有哪些Behavior可用?

    首先在Expression Blend控件库左边的behavior部分已经有好多实现的行为,可直接拖过来用,当然网上资源也很多(如这个),还能自己扩展。

    behavior

    自定义Behavior

    举个例子,Silverlight文本框的一个老问题就是它只在失去焦点的时候才更新绑定源,失去焦点才做Validation,我们来编写一个behavior可以简单的解决这个问题:textbox文字改变就立即validation并更新绑定数据源。下载本CustomBehavior示例源代码

    代码:

    TextBoxUpdateBehavior : Behavior
    1 using System;
    2 using System.Net;
    3 using System.Windows;
    4 using System.Windows.Controls;
    5 using System.Windows.Documents;
    6 using System.Windows.Ink;
    7 using System.Windows.Input;
    8 using System.Windows.Media;
    9 using System.Windows.Media.Animation;
    10 using System.Windows.Shapes;
    11 using System.Windows.Interactivity;
    12
    13 namespace AsycValidation
    14 {
    15 public class TextBoxUpdateBehavior : Behavior<TextBox>
    16 {
    17 public TextBoxUpdateBehavior()
    18 {
    19 }
    20 protected override void OnAttached()
    21 {
    22 base.OnAttached();
    23 AssociatedObject.TextChanged += AssociatedObjectOnTextChanged;
    24 }
    25 private void AssociatedObjectOnTextChanged(object sender, TextChangedEventArgs args)
    26 {
    27 var bindingExpr = AssociatedObject.GetBindingExpression(TextBox.TextProperty);
    28 bindingExpr.UpdateSource();
    29
    30 }
    31 protected override void OnDetaching()
    32 {
    33 base.OnDetaching();
    34 AssociatedObject.TextChanged -= AssociatedObjectOnTextChanged;
    35 }
    36 }
    37 }

    xaml

    Xaml code
    <UserControl xmlns:wm="clr-namespace:AsycValidation"
    <TextBox Height
    ="30" HorizontalAlignment="Left" Margin="120,104,0,0" x:Name="textBox2" Text="{Binding CompanyID, Mode=TwoWay, NotifyOnValidationError=True}" VerticalAlignment="Top" Width="119" >
    <i:Interaction.Behaviors>
    <wm:TextBoxUpdateBehavior/>
    </i:Interaction.Behaviors>
    </TextBox>
    </UserControl>

    (运行后如何看效果:在第二个textbox输入1,输入2,输入1,看看validation)下载本CustomBehavior示例源代码

    (本示例同时演示了Behavior, CustomBehavior, Validation, INotifyPropertyChanged, INotifyDataErrorInfo, MVVM, WCF Ria Service, 异步validation...)

    Powered By D&J (URL:http://www.cnblogs.com/Areas/)
  • 相关阅读:
    st-load视频性能测试
    gitlab-ci集成SonarQube代码质量检查
    退役记
    洛谷 P5195 【[USACO05DEC]Knights of Ni S】
    洛谷 P4742 【[Wind Festival]Running In The Sky】
    洛谷 SP13105 【MUTDNA
    洛谷 P3174 【[HAOI2009]毛毛虫】
    洛谷 P1542 【包裹快递】
    Python函数的返回值
    ubuntu18.04修改国内apt源
  • 原文地址:https://www.cnblogs.com/Areas/p/2169886.html
Copyright © 2011-2022 走看看