silverlighter下MVVM模式中利用Behavior和TargetedTriggerAction实现文本框的一些特效

简介:   在silverlight一般开发模式中,给文本框添加一些事件是轻而易举的,然而MVVM开发模式中,想要给文本框添加一些事件并非那么容易,因为MVVM模式中,只有ICommand接口,而且也只有Button中才有Command属性,通过ViewModel可以将方法绑定到Button上面,却无法绑定到文本框和其他一些控件。

  在silverlight一般开发模式中,给文本框添加一些事件是轻而易举的,然而MVVM开发模式中,想要给文本框添加一些事件并非那么容易,因为MVVM模式中,只有ICommand接口,而且也只有Button中才有Command属性,通过ViewModel可以将方法绑定到Button上面,却无法绑定到文本框和其他一些控件。、

  Behavior的出现解决了这一难题,下面就来说一下具体的实现方法:

  实例一:在用户登录窗口,用户点击Reset按钮后,让用户名输入框自动获取焦点。

  首先要先将ViewModel绑定到我们的控件上面,我们一步一步来做,第一步先写Model,下面是Model的代码:

  

using System;
using System.Net;
using System.Runtime.Serialization;
using System.ComponentModel;

namespace BookModel
{
   [DataContract]
   public class UserModel : INotifyPropertyChanged
   {
      public event PropertyChangedEventHandler PropertyChanged;

      private string userName = String.Empty;
      private string passWord = String.Empty;

      [DataMember]
      public string UserName
      {
         get { return userName; }
         set { userName = value; OnPropertyChanged("UserName"); }
      }

      [DataMember]
      public string PassWord
      {
         get { return passWord; }
         set { passWord = value; OnPropertyChanged("PassWord"); }
      }

      /// <summary>
      /// Call the event PropertyChanged.
      /// </summary>
      /// <param name="PropertyName"></param>
      public void OnPropertyChanged(string PropertyName)
      {
         if (PropertyChanged != null)
         {
            PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
         }
      }
   }
}

 

  写完了Model,下一步就是写ViewModel了,在ViewModel中引用Model的命名控件,下面是ViewModel的代码,例子比较简单,就不多解释了。

  

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using BookModel;
using System.Windows.Browser;

namespace BookViewModel
{
   public class VM_User
   {
      /// <summary>
      /// In the Constructors create the instance of User.
      /// </summary>
      public VM_User()
      {
         user = new UserModel();
         user.UserName = "Jack";
      }

      public UserModel user { get; set; }
      public LoginCommand Login
      {
         get { return new LoginCommand(); }
      }
      public ResteCommand Reset
      {
         get { return new ResteCommand(); }
      }
   }

   /// <summary>
   /// Login Button's method
   /// </summary>
   public class LoginCommand:ICommand
   {
      public bool CanExecute(object parameter)
      {
         return true;
      }

      public void Execute(object parameter)
      {
         VM_User VMUser = parameter as VM_User;
         if (VMUser.user.UserName.Equals("admin") && VMUser.user.PassWord.Equals("123"))
         {
            MessageBox.Show("Login success!", "System Info", MessageBoxButton.OK);
         }
         else
         {
            MessageBox.Show("Login failed!", "System Info", MessageBoxButton.OK);
         }
      }

      public event EventHandler CanExecuteChanged;
   }

   /// <summary>
   /// Reset buttom's method
   /// </summary>
   public class ResteCommand : ICommand
   {
      public bool CanExecute(object parameter)
      {
         return true;
      }

      public void Execute(object parameter)
      {
         VM_User VMUser = parameter as VM_User;
         VMUser.user.UserName = "";
         VMUser.user.PassWord = "";
      }
      public event EventHandler CanExecuteChanged;
   }
}
View Code

  这里就不连接数据库了,那样代码量太大,也不方便大家查看。这里只做一个简单的验证,至此MVVM中的M和VM就都建好了,下面写前端的显示层,添加两个TextBlock和两个TextBox,两个按钮。用作登录用,分别为用户名,密码,登录和重置。

  下面是绑定代码:

  

<UserControl x:Class="BookLibrary.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
    xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
    xmlns:local="clr-namespace:BookViewModel;assembly=BookViewModel"
    mc:Ignorable="d"
    d:DesignHeight="600" d:DesignWidth="1000" 
    xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
    xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation">

   <UserControl.Resources>
      <local:VM_User x:Key="User" />
   </UserControl.Resources>
    <Grid x:Name="LayoutRoot" Background="White" DataContext="{Binding Source={StaticResource User}}" Loaded="LayoutRoot_Loaded">
      <telerik:RadBusyIndicator Name="BusyIndicator">
         <Border>
            <Border.Background>
               <LinearGradientBrush EndPoint="0.5 1" StartPoint="0.5 0">
                  <GradientStop Color="#0369a9" Offset="0" />
                  <GradientStop Color="#046daf" Offset="0.5" />
                  <GradientStop Color="#2fa2e5" Offset="1" />
               </LinearGradientBrush>
            </Border.Background>
            <Border VerticalAlignment="Center" HorizontalAlignment="Center">
               <Border.Effect>
                  <DropShadowEffect BlurRadius="10" Opacity="0.4"/>
               </Border.Effect>
               <Border.Background>
                  <RadialGradientBrush>
                     <GradientStop Color="#0B7AC1" Offset="0" />
                     <GradientStop Color="#1182c7" Offset="1" />
                  </RadialGradientBrush>
               </Border.Background>
               <Grid>
                  <Grid.RowDefinitions>
                     <RowDefinition Height="60"/>
                     <RowDefinition Height="15"/>
                     <RowDefinition Height="45"/>
                     <RowDefinition Height="45"/>
                     <RowDefinition Height="60"/>
                  </Grid.RowDefinitions>
                  <Grid.ColumnDefinitions>
                     <ColumnDefinition Width="185"/>
                     <ColumnDefinition Width="90"/>
                     <ColumnDefinition Width="160"/>
                     <ColumnDefinition Width="100"/>
                  </Grid.ColumnDefinitions>
                  <TextBlock VerticalAlignment="Center" HorizontalAlignment="Left" 
                             Grid.Row="0" Grid.Column="0" Margin="20,0,0,0" FontWeight="Bold"   
                             Text="School System |" FontSize="16" Foreground="White"/>
                  <TextBlock Grid.Row="0" Grid.Column="1" HorizontalAlignment="Left" 
                             VerticalAlignment="Center" Text="User Login" FontSize="14"
                             Foreground="#b4e6ec"/>
                  <Image Source="Images/LoginPicture.png" Grid.Row="1" Grid.Column="0" Grid.RowSpan="3" />
                  <TextBlock FontSize="14" Grid.Row="2" Grid.Column="1" Text="UserName:" 
                             Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Left" />
                  <TextBlock FontSize="14" Grid.Row="3" Grid.Column="1" Text="PassWord:" 
                             Foreground="White" VerticalAlignment="Center" HorizontalAlignment="Left" />
                  <TextBox Name="txtName"  Text="{Binding user.UserName,Mode=TwoWay}" HorizontalAlignment="Left" FontSize="14" Grid.Row="2" Grid.Column="2" Width="150" Height="26" />
                  <PasswordBox Password="{Binding user.PassWord,Mode=TwoWay}" HorizontalAlignment="Left" Grid.Row="3" Grid.Column="2" Width="150" Height="26" />
                  <Button Command="{Binding Login}" CommandParameter="{Binding}" HorizontalAlignment="Left" Width="80" Height="26" Grid.Row="2" Grid.Column="3" Content="Login" Click="Button_Click_1" />
                  <Button Command="{Binding Reset}" CommandParameter="{Binding}" HorizontalAlignment="Left" Width="80" Height="26" Grid.Row="3" Grid.Column="3" Content="Reset" Click="Button_Click" />
                  <CheckBox HorizontalAlignment="Left" VerticalAlignment="Top" Margin="0,10,0,0" Grid.Row="4" Grid.Column="2" Content="Save State" Foreground="White" />

               </Grid>
            </Border>
         </Border>
      </telerik:RadBusyIndicator>

   </Grid>
</UserControl>

  这个时候,就实现登录和重置功能了,但是重置的时候用户名文本框并不会获得焦点,下面我们来讲实现方法:

  第一种方法:TargetedTriggerAction绑定

  先写一个类,叫做TextBoxGetFocusBahavior,代码如下:

  

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Interactivity;

namespace BookLibrary
{
   public class TextBoxGetFocusBahavior:TargetedTriggerAction<TextBox>
   {
      public void GotFocusAction()
      {

      }
      protected override void Invoke(object parameter)
      {
         TextBox targetTextBox = Target;
         targetTextBox.SelectAll();
      }
   }
}
View Code

  然后在前台绑定,绑定方法如下:

  

xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity"
<TextBox Height="23" Name="textBox" HorizontalAlignment="Left" Margin="36,28,0,0" VerticalAlignment="Top" Width="198"> <i:Interaction.Triggers> <i:EventTrigger EventName="GotFocus"> <local:TextBoxGetFocusBahavior TargetName="textBox" /> </i:EventTrigger> </i:Interaction.Triggers> </TextBox>

  注意我标红的地方,就是要引入命名空间。

 

  第二种方法Behavior方法,和上面基本一样,不过我感觉这种方法比较灵活,推荐使用这种方法。新加一个类,AutoSetFocusBehavior,代码如下:

  

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Interactivity;

namespace BookLibrary
{
   public class AutoSetFocusBehavior:Behavior<TextBox>
   {
      protected override void OnAttached()
      {
         base.OnAttached();
         AssociatedObject.TextChanged += OnTextChanged;
      }

      public void OnTextChanged(object sender, EventArgs e)
      {
         if(AssociatedObject.Text.Equals(""))
            AssociatedObject.Focus();
      }
   }
}
View Code

  这里前端绑定方法为:

  

 <TextBox Text="{Binding user.UserName}" x:Name="txtName" Height="27" HorizontalAlignment="Left" Margin="36,76,0,0" VerticalAlignment="Top" Width="332">
         <i:Interaction.Behaviors>
            <local:AutoSetFocusBehavior />
         </i:Interaction.Behaviors>
      </TextBox>

  注意,同样要引入上面的命名空间。

  其实,说了这么多,就是给TextBox加了个OnTextChanged事件,当内容被清空时,判断内容是否为空,为空则设置焦点。

  希望这篇文章能给大家一点帮助。不足之处,还请赐教。

 

目录
相关文章
|
6月前
EasyUI中datagrid的行编辑模式中,找到特定的Editor,并为其添加事件
EasyUI中datagrid的行编辑模式中,找到特定的Editor,并为其添加事件
|
前端开发 C# 图形学
【WPF】WPF开发用户控件、用户控件属性依赖DependencyProperty实现双向绑定、以及自定义实现Command双向绑定功能演示
Wpf开发过程中,最经常使用的功能之一,就是用户控件(UserControl)了。用户控件可以用于开发用户自己的控件进行使用,甚至可以用于打造一套属于自己的UI框架。依赖属性(DependencyProperty)是为用户控件提供可支持双向绑定的必备技巧之一,同样用处也非常广泛。
791 0
【WPF】WPF开发用户控件、用户控件属性依赖DependencyProperty实现双向绑定、以及自定义实现Command双向绑定功能演示
|
图形学
Unity 编辑器开发实战【Custom Editor】- 为UI视图制作动画编辑器
Unity 编辑器开发实战【Custom Editor】- 为UI视图制作动画编辑器
199 1
Unity 编辑器开发实战【Custom Editor】- 为UI视图制作动画编辑器
|
JavaScript 前端开发 Shell
SAP UI5 按钮渲染原理
SAP UI5 按钮渲染原理
SAP UI5 按钮渲染原理
使用SAP C4C rule editor动态控制UI上某个按钮是否显示
使用SAP C4C rule editor动态控制UI上某个按钮是否显示
使用SAP C4C rule editor动态控制UI上某个按钮是否显示
SAP UI5 的控件Focus 相关处理逻辑
tap, keydown, keypress sap.ui.core.FocusHandler sap.ca.scfld.md.app.CommonHeaderFooterHelper event = new jQuery.Event(originalEvent); focusin, activate, blur, focusout, sapfocusleave oElement._handleEvent(oEvent);
103 0
SAP UI5 的控件Focus 相关处理逻辑
|
前端开发 JavaScript Shell
UI5按钮渲染原理
To debug how is a button rendered in UI5 I created a project by using SAPUI5 application template via Web IDE. And add a button in View1.view.xml as below:
UI5按钮渲染原理
|
前端开发 C#
WPF MVVM模式下实现ListView下拉显示更多内容
原文:WPF MVVM模式下实现ListView下拉显示更多内容 在手机App中,如果有一个展示信息的列表,通常会展示很少一部分,当用户滑动到列表底部时,再加载更多内容。这样有两个好处,提高程序性能,减少网络流量。
1513 0
|
前端开发 C# 数据格式
WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制
原文:WPF MVVM模式中,通过命令实现窗体拖动、跳转以及显隐控制 在WPF中使用MVVM模式,可以让我们的程序实现界面与功能的分离,方便开发,易于维护。但是,很多初学者会在使用MVVM的过程中遇到一个显而易见且无法回避的问题,那就是不同的窗体之间如何跳转?很多人在介绍MVVM的使用时,都没有明显提到该如何解决这一问题,不知是因为觉得太简单了还是其他原因。
2511 0
|
前端开发 C#
使用MVVM DataTriggers在WPF XAML视图之间切换/Window窗口自适应内容大小并居中
原文 使用MVVM DataTriggers在WPF XAML视图之间切换 相关文章: http://www.technical-recipes.com/2016/switching-between-wpf-xaml-views-using-mvvm-datatemplate/ 这篇文章解决了能够根据ViewModel类的属性在不同视图之间切换的问题。
1791 0