背景
本文通过一个简单的按钮权限来描述如何使用IValueConverter接口。
首先可以看到IValueConverter包含两个接口方法:
object Convert(object value, Type targetType, object parameter, CultureInfo culture);
以及
object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
实现了源数据类型以及目标数据类型之间的转换。
详细分析
1. 该按钮权限分为4种状态:查询,修改,添加,删除;用户的权限可以是4种状态中的任意组合;
比如3级用户只拥有查询的权限;2级用户拥有查询和修改的权限;超级管理员拥有所有状态的权限;
UI上的显示很简单,如果有权限,按钮则显示;无权限,按钮就不显示;
2. 有些人考虑这个问题的时候,可能会想到在数据库设计这个权限的时候,会使用字符串形式,如“1”表示拥有查询权限,“1,3”表示拥有查询和添加权限,“1,2,3,4”表示拥有所有权限。而我这里考虑是采用位运算的方式进行处理;考虑到4种状态,我先创建一个用户权限枚举类型

/// 用户权限
/// </summary>
public enum UserRight
{
None = 0 ,
/// <summary>
/// 查询权限(1)
/// </summary>
Select = 1 ,
/// <summary>
/// 修改权限(2)
/// </summary>
Update = 2 ,
/// <summary>
/// 插入权限(3)
/// </summary>
Insert = 3 ,
/// <summary>
/// 删除权限(4)
/// </summary>
Delete = 4
}
根据4种状态的组合,可以得到15种情况的组合;所以通过1—15整型数值,可以对应每一种的组合情况,这样可以通过一个枚举扩展方法进行实现:

/// 将复合权限类型ID 转换成 权限枚举类型数组
/// </summary>
/// <param name="userRightComplex"></param>
/// <returns></returns>
public static UserRight[] ToUserRightArray( this int userRightComplex)
{
int max = EnumHelper.GetValues( typeof (UserRight)).Length - 2 ; // 除去None枚举,并需要再减1,所以减2
List < UserRight > userRightList = null ;
while (userRightComplex > 0 )
{
if (userRightList == null )
userRightList = new List < UserRight > ();
int arg = Convert.ToInt32(Math.Pow( 2 , max));
if (userRightComplex >= arg)
{
userRightComplex -= arg;
userRightList.Add((UserRight)Enum.Parse( typeof (UserRight), (max + 1 ).ToString(), true ));
}
max -- ;
}
if (userRightList == null || userRightList.Count == 0 )
{
return null ;
}
return userRightList.ToArray();
}
这样,通过一个整型值可以得到一个用户权限的数组。
如1得到一个“查询”数组,5得到一个“查询、添加”数组,15得到所有状态的数组;
这样做的目的是为了对于用户权限表可以减少数据库数据存储量,以及能够提高数据库查询的性能;
3. 添加一个UserRightControl类,用于用户数据传递:

{
/// <summary>
/// 复合权限类型ID
/// </summary>
public int UserRightComplex { get ; set ; }
/// <summary>
/// 权限数组
/// </summary>
private UserRight[] _rights;
public UserRight[] UserRights
{
get
{
if (_rights == null )
{
// 将复合权限类型ID 转换成 权限枚举类型数组
_rights = UserRightComplex.ToUserRightArray();
}
return _rights;
}
}
}
4. 创建一个继承于IValueConverter接口的UserRightConverter

{
public object Convert( object value, Type targetType, object parameter, CultureInfo culture)
{
Visibility visibility = Visibility.Collapsed;
UserRight[] rightArray = (UserRight[])value;
UserRight right = (UserRight)Enum.Parse( typeof (UserRight), ( string )parameter, true );
UserRight state = rightArray.FirstOrDefault(o => o == right);
if (state != UserRight.None)
{
visibility = Visibility.Visible;
}
return visibility;
}
public object ConvertBack( object value, Type targetType, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
其中value是作为一个用户权限数组绑定过来的,parameter作为对应按钮的属性参数,如果value包含了parameter,该按钮就显示。
5. 接着,创建一个UserRightButton.xaml的用户权限按钮控件:

xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation%22
xmlns:x=" http://schemas.microsoft.com/winfx/2006/xaml%22
xmlns:uc ="clr-namespace:SilverlightAppDemo" >
< UserControl.Resources >
< uc:UserRightConverter x:Key ="userRightConverter" />
< Style x:Key ="userright" TargetType ="Button" >
< Setter Property ="Height" Value ="30" />
< Setter Property ="Width" Value ="60" />
< Setter Property ="FontSize" Value ="14" />
</ Style >
</ UserControl.Resources >
< StackPanel HorizontalAlignment ="Left" >
< StackPanel Orientation ="Horizontal" >
< Button Content ="查询" Visibility ="{Binding UserRights, Converter={StaticResource userRightConverter}, ConverterParameter=Select}" Style ="{StaticResource userright}" ></ Button >
< Button Content ="修改" Visibility ="{Binding UserRights, Converter={StaticResource userRightConverter}, ConverterParameter=Update}" Style ="{StaticResource userright}" ></ Button >
< Button Content ="添加" Visibility ="{Binding UserRights, Converter={StaticResource userRightConverter}, ConverterParameter=Insert}" Style ="{StaticResource userright}" ></ Button >
< Button Content ="删除" Visibility ="{Binding UserRights, Converter={StaticResource userRightConverter}, ConverterParameter=Delete}" Style ="{StaticResource userright}" ></ Button >
</ StackPanel >
</ StackPanel >
</ UserControl >
该用户控件用于权限按钮的UI显示,注意到Button的Visibility属性,Binding UserRight 绑定了 UserRightControl类中的UserRights的权限数组;Converter={StaticResource userRightConverter} 将以userRightConverter为Key的UserRightConverter类 作为按钮的转换器,ConverterParameter后面的值为parameter。
6. 最后,在Page.xaml上添加用户权限按钮控件:

xmlns ="http://schemas.microsoft.com/winfx/2006/xaml/presentation%22
xmlns:x=" http://schemas.microsoft.com/winfx/2006/xaml%22
xmlns:uc ="clr-namespace:SilverlightAppDemo" >
< UserControl.Resources >
< uc:UserRightControl UserRightComplex ="1" x:Key ="urControl" />
</ UserControl.Resources >
< StackPanel >
< uc:UserRightButton x:Name ="btnUserRight" DataContext ="{StaticResource urControl}" />
</ StackPanel >
</ UserControl >
其中UserRightButton中的DataContext属性绑定了以urControl为Key的UserRightControl。
7. 运行下程序
当UserRightComplex为1时,
当UserRightComplex为5时,
当UserRightComplex为15时,
本文主要介绍如何使用IValueConverter在应用场景中,欢迎继续交流。
源代码下载:SilverlightAppDemo.rar