SilverLight学习笔记--利用DependencyProperty依赖属性创建自备录入过滤功能的TextBox控件...

本文介绍如何在Silverlight中创建具备录入过滤功能的自定义TextBox控件,并通过不同类型的过滤属性实现对输入内容的限制。
      在这里我们要创建一个具备录入过滤功能的TextBox控件,我们为此控件创建了一个名为FilterProperty的依赖属性和一个名为MyFilter的CLR属性,我们通过设置MyFilter属性来影响此TextBox控件的录入过滤效果,例如:当我们设置MyFilter属性为Alpha时,我们在此TextBox控件中敲击任何数字键将不会有什么反应,因为此时,它只接受英文字母。其余的过滤效果以此类推。
       一、创建我们的这个自定义控件。
      打开VS2008,新建一个Silverlight类库,命名为:SLFilterTextBox,创建如下图
                             
  把Class1.cs改名为MyFilterTextBox.cs,其全部代码如下:
                           
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;

namespace  SLFilterTextBox
ExpandedBlockStart.gifContractedBlock.gif
{
ContractedSubBlock.gifExpandedSubBlockStart.gif    
过滤类型枚举值#region 过滤类型枚举值
    
public enum TextBoxFilterType
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{
        None,
        PositiveInteger,
        Integer,
        PositiveDecimal,
        Decimal,
        Alpha,
    }

    
#endregion


    
public class MyFilterTextBox:TextBox
ExpandedSubBlockStart.gifContractedSubBlock.gif    
{

ContractedSubBlock.gifExpandedSubBlockStart.gif        
声明一个依赖属性FilterProperty#region 声明一个依赖属性FilterProperty
        
public static readonly DependencyProperty FilterProperty;
        
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif        
定义一个CLR属性MyFilter来操作依赖属性FilterProperty#region 定义一个CLR属性MyFilter来操作依赖属性FilterProperty
        
//因为依赖属性不能像普通CLR属性那样直接赋值,依赖属性不能直接使用,所以我们只能隔山打牛,通过定义一个CLR属性来屏蔽对依赖属性的操作
        
//而具体操作的实现是通过定义GetFilter()方法以及SetFilter()方法来达到
        public TextBoxFilterType MyFilter
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
get
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return GetFilter(this); //得到当前的FilterProperty依赖属性值
            }

            
set
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                SetFilter(
this, value);  //设置当前的FilterProperty依赖属性值
            }

        }

        
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif        
定义GetFilter()与SetFilter()方法来间接操作Filter property依赖属性#region 定义GetFilter()与SetFilter()方法来间接操作Filter property依赖属性

ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// 取得 Filter property依赖属性值. 
        public static TextBoxFilterType GetFilter(DependencyObject d)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
return (TextBoxFilterType)d.GetValue(FilterProperty);
        }


ExpandedSubBlockStart.gifContractedSubBlock.gif        
/**//// 设置 Filter property 依赖属性值
        public static void SetFilter(DependencyObject d, TextBoxFilterType value)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            d.SetValue(FilterProperty, value);
        }

        
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif        
静态构造函数(在此构造函数中注册上面声明的依赖属性)#region 静态构造函数(在此构造函数中注册上面声明的依赖属性)
        
static MyFilterTextBox()
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
             
//在静态构造函数中注册此依赖属性
             
//因为依赖属性需要用DependencyProperty的Register静态方法来创建
              FilterProperty =DependencyProperty.Register("Filter",
                                                    
typeof(TextBoxFilterType),//此属性数据类型属于上面定义的过滤类型枚举值
                                                    typeof(MyFilterTextBox), //指定此依赖属性的所有者是MyFilterTextBox控件(一般是当前代码所在的类)
                                                    new PropertyMetadata(OnFilterChanged)); //当依赖属性值改变时会触发此委托OnFilterChanged

              
        }

        
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif        
OnFilterChanged委托负责给TextBox的keyDown事件定义不同的行为约束#region OnFilterChanged委托负责给TextBox的keyDown事件定义不同的行为约束
        
//也即:当给MyFilterTextBox控件的MyFilter属性赋值时,通过OnFilterChanged来判断当前MyFilter属性是何值
        
//并根据不同的取值赋予MyFilterTextBox控件不同的KeyDown行为特征
        private static void OnFilterChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            TextBox textBox 
= d as TextBox;
            
if (TextBoxFilterType.None != (TextBoxFilterType)e.OldValue)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                textBox.KeyDown 
-= new KeyEventHandler(textBox_KeyDown);
            }

            
if (TextBoxFilterType.None != (TextBoxFilterType)e.NewValue)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                textBox.KeyDown 
+= new KeyEventHandler(textBox_KeyDown);
            }

        }

        
#endregion
 

ContractedSubBlock.gifExpandedSubBlockStart.gif        
TextBox控件的KeyDown事件行为定义#region TextBox控件的KeyDown事件行为定义

ContractedSubBlock.gifExpandedSubBlockStart.gif        
textBox_KeyDown 事件委托处理(根据不同的filterType,赋予不同的Handled)#region textBox_KeyDown 事件委托处理(根据不同的filterType,赋予不同的Handled)
        
private static void textBox_KeyDown(object sender, KeyEventArgs e)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
// bypass other keys!
            if (IsValidOtherKey(e.Key))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return;
            }

            
//
            TextBoxFilterType filterType = GetFilter((DependencyObject)sender);
            TextBox textBox 
= sender as TextBox;
            
if (null == textBox)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                textBox 
= e.OriginalSource as TextBox;
            }

            
//
            switch (filterType)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
case TextBoxFilterType.PositiveInteger:
                    e.Handled 
= !IsValidIntegerKey(textBox, e.Key, e.PlatformKeyCode, false);
                    
break;
                
case TextBoxFilterType.Integer:
                    e.Handled 
= !IsValidIntegerKey(textBox, e.Key, e.PlatformKeyCode, true);
                    
break;
                
case TextBoxFilterType.PositiveDecimal:
                    e.Handled 
= !IsValidDecmialKey(textBox, e.Key, e.PlatformKeyCode, false);
                    
break;
                
case TextBoxFilterType.Decimal:
                    e.Handled 
= !IsValidDecmialKey(textBox, e.Key, e.PlatformKeyCode, true);
                    
break;
                
case TextBoxFilterType.Alpha:
                    e.Handled 
= !IsValidAlphaKey(e.Key);
                    
break;
            }

        }

        
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif        
允许除数字与字母外的其它允许的按键#region 允许除数字与字母外的其它允许的按键
        
private static bool IsValidOtherKey(Key key)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
// allow control keys
            if ((Keyboard.Modifiers & ModifierKeys.Control) != 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return true;
            }

            
// allow
            
// Back, Tab, Enter, Shift, Ctrl, Alt, CapsLock, Escape, PageUp, PageDown
            
// End, Home, Left, Up, Right, Down, Insert, Delete 
            
// except for space!
            
// allow all Fx keys
            if (
                (key 
< Key.D0 && key != Key.Space)
                
|| (key > Key.Z && key < Key.NumPad0))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return true;
            }

            
// we need to examine all others!
            return false;
        }

        
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif        
允许整数数字键#region 允许整数数字键
        
private static bool IsValidIntegerKey(TextBox textBox, Key key, int platformKeyCode, bool negativeAllowed)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
if ((Keyboard.Modifiers & ModifierKeys.Shift) != 0)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return false;
            }

            
if (Key.D0 <= key && key <= Key.D9)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return true;
            }

            
if (Key.NumPad0 <= key && key <= Key.NumPad9)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return true;
            }

            
if (negativeAllowed && (key == Key.Subtract || (key == Key.Unknown && platformKeyCode == 189)))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return 0 == textBox.Text.Length;
            }

            
//
            return false;
        }

        
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif        
允许小数数字键#region 允许小数数字键
        
private static bool IsValidDecmialKey(TextBox textBox, Key key, int platformKeyCode, bool negativeAllowed)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
if (IsValidIntegerKey(textBox, key, platformKeyCode, negativeAllowed))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return true;
            }

            
if (key == Key.Decimal || (key == Key.Unknown && platformKeyCode == 190))
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return !textBox.Text.Contains(".");
            }

            
return false;
      
      //
        }

        
#endregion


ContractedSubBlock.gifExpandedSubBlockStart.gif        
允许字母键#region 允许字母键
        
private static bool IsValidAlphaKey(Key key)
ExpandedSubBlockStart.gifContractedSubBlock.gif        
{
            
if (Key.A <= key && key <= Key.Z)
ExpandedSubBlockStart.gifContractedSubBlock.gif            
{
                
return true;
            }

            
//
            return false;
            
//
        }

        
#endregion

        
#endregion

    }

}


 这样,我们就创建了我们的自定义TextBox控件,现在我们来应用它。

  二、应用我们创建的TextBox控件
   现在我们新建一个Silverlight应用程序,命名为MySLTextBoxTest,创建后如下图:
                        
在项目MySLTextBoxTest中添加引用--浏览--引入我们前面生成的自定义控件(SLFilterTextBox.dll)。
                        
引入后程序如下图:

                        

  接下来先编辑我们的界面,Page.xaml代码如下:
 
< UserControl x:Class = " MySLTextBoxTest.Page "
    xmlns
= " http://schemas.microsoft.com/winfx/2006/xaml/presentation "  
    xmlns:x
= " http://schemas.microsoft.com/winfx/2006/xaml "  
    xmlns:mysrc
= " clr-namespace:SLFilterTextBox;assembly=SLFilterTextBox "
    Width
= " 450 "  Height = " 300 " >
  
< Canvas Width = " 450 "  Height = " 300 "  Background = " Wheat "  HorizontalAlignment = " Center " >
      
< TextBlock Margin = " 10,20,20,20 "  Text = " 自定义TextBox示例 "  Foreground = " Green "   FontSize = " 18 "  Width = " 200 "  HorizontalAlignment = " Center "   ></ TextBlock >
    
< Grid Width = " 400 "  Height = " 300 "  Margin = " 10,60,20,20 "   >
        
< Grid.RowDefinitions >
            
< RowDefinition Height = " Auto " />
            
< RowDefinition Height = " Auto " />
            
< RowDefinition Height = " Auto " />
            
< RowDefinition Height = " Auto " />
            
< RowDefinition Height = " Auto " />
            
< RowDefinition Height = " Auto " />
            
< RowDefinition Height = " Auto " />
        
</ Grid.RowDefinitions >
        
< Grid.ColumnDefinitions >
            
< ColumnDefinition Width = " * "   />
            
< ColumnDefinition Width = " * " />
        
</ Grid.ColumnDefinitions >
    
        
< TextBlock Grid.Column = " 0 "  Text = " 请输入正整数 "   />
        
< mysrc:MyFilterTextBox x:Name = " txtBxPositiveInteger "  Grid.Column = " 1 " ></ mysrc:MyFilterTextBox >
    
        
< TextBlock Grid.Column = " 0 "  Grid.Row = " 2 "  Text = " 请输入整数 " />
        
< mysrc:MyFilterTextBox x:Name = " txtBxOnlyInteger "  Grid.Row = " 2 "   Grid.Column = " 1 " ></ mysrc:MyFilterTextBox >
    
        
< TextBlock Grid.Column = " 0 "  Grid.Row = " 3 "  Text = " 请输入正小数 " />
        
< mysrc:MyFilterTextBox x:Name = " txtBxOnlyPositiveDecimal "  Grid.Column = " 1 "  Grid.Row = " 3 "   ></ mysrc:MyFilterTextBox >
    
        
< TextBlock Grid.Column = " 0 "  Grid.Row = " 4 "  Text = " 请输入小数 " />
        
< mysrc:MyFilterTextBox x:Name = " txtBxOnlyDecimal "  Grid.Column = " 1 "  Grid.Row = " 4 "   ></ mysrc:MyFilterTextBox >

        
< TextBlock Grid.Column = " 0 "  Grid.Row = " 5 "  Text = " 请输入字母 " />
        
< mysrc:MyFilterTextBox x:Name = " txtBxOnlyAlphabets "  Grid.Column = " 1 "  Grid.Row = " 5 "
                             
>   </ mysrc:MyFilterTextBox >
    
</ Grid >
    
</ Canvas >
</ UserControl >
 在此代码中,我们要引入我们的自定义控件的程序集:
 xmlns:mysrc = " clr-namespace:SLFilterTextBox;assembly=SLFilterTextBox "
然后,我们在后台代码中设置自定义TextBox控件的MyFilter属性,Page.xaml.cs全部代码如下:
using  System;
using  System.Collections.Generic;
using  System.Linq;
using  System.Net;
using  System.Windows;
using  System.Windows.Controls;
using  System.Windows.Documents;
using  System.Windows.Input;
using  System.Windows.Media;
using  System.Windows.Media.Animation;
using  System.Windows.Shapes;
using  SLFilterTextBox;  // 引入我们自定义控件空间

namespace  MySLTextBoxTest
{
    
public   partial   class  Page : UserControl
    {
        
public  Page()
        {
            InitializeComponent();

            Loaded
+= new  RoutedEventHandler(Page_Loaded);
        }

        
private   void  Page_Loaded( object  sender, RoutedEventArgs e)
        {
            
this .txtBxOnlyAlphabets.MyFilter  =  SLFilterTextBox.TextBoxFilterType.Alpha;
            
this .txtBxOnlyDecimal.MyFilter  =  SLFilterTextBox.TextBoxFilterType.Decimal;
            
this .txtBxOnlyInteger.MyFilter  =  SLFilterTextBox.TextBoxFilterType.Integer;
            
this .txtBxOnlyPositiveDecimal.MyFilter  =  SLFilterTextBox.TextBoxFilterType.PositiveDecimal;
            
this .txtBxPositiveInteger.MyFilter  =  SLFilterTextBox.TextBoxFilterType.PositiveInteger;
        }
    }
}
生成项目后F5运行,效果如图:
                        
我们可以不按要求在TextBox中录入数据,可以看到相关录入过滤效果。


前往:Silverlight学习笔记清单
本文程序在Silverlight2.0和VS2008环境中调试通过。本文参照了部分网络资料,希望能够抛砖引玉,大家共同学习。
(转载本文请注明出处)

转载于:https://www.cnblogs.com/wsdj-ITtech/archive/2009/09/11/1564463.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值