背景
本文通过一个简单的按钮权限来描述如何使用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>
///
用户权限
///
</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整型数值,可以对应每一种的组合情况,这样可以通过一个枚举扩展方法进行实现:
代码
///
<summary>
///
将复合权限类型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类,用于用户数据传递:
代码
public
class
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
class
UserRightConverter : IValueConverter
{
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的用户权限按钮控件:
代码
<
UserControl
x:Class
="SilverlightAppDemo.UserRightButton"
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上添加用户权限按钮控件:
代码
<
UserControl
x:Class
="SilverlightAppDemo.Page"
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