本文主要讲解如何使用IValueConverter和TypeConverter。我们通过两个思考问题来引入如何使用IValueConverter和TypeConverter!
IValueConverter主要用于将数据源的数据转换为需要在界面上显示的数据,例如:将Url地址转换为图片显示到界面上、将float类型数据显示为货币类型、bool值和Visibility转换等等。
TypeConverter主要用于在XAML代码中的字符串类型转换为其他类型的数值,比如将一段字符串转为Double类型以供Width属性使用。
思考一:我的数据集合的其中一个集合中的属性为某个图片的URL,如何将这个URL地址转换为图片显示到DataGrid行中呢?
IValueConverter的使用方法:
一、首先编写一个ImageConverter类型,此类继承于IValueConverter接口,然后实现此接口的Convert和ConvertBack方法。注意Convert方法是将数据源的数据转为需要显示的数据,而ConvertBack方法用于将显示出来的数据在TwoWay模式下回传给数据源。如下面的代码以编制:
public class ImageConverter : IValueConverter
{
// 在载入数据的时候将数据转换为图片类型
public object Convert( object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
try
{
Uri uri = new Uri(( string )value, UriKind.RelativeOrAbsolute);
BitmapImage img = new BitmapImage(uri);
return img;
}
catch
{
return new BitmapImage();
}
}
// 在页面上操作的时候,将图片类型转换为数据,这里只有再TwoWay的时候才有用
public object ConvertBack( object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
BitmapImage img = value as BitmapImage;
return img.UriSource.AbsoluteUri;
}
}
< UserControl.Resources >
< this :ImageConverter x:Key = " ImageCoverter " />
</ UserControl.Resources >
< sdk:DataGrid HorizontalAlignment = " Left " AutoGenerateColumns = " False " Name = " ShowCityList " VerticalAlignment = " Top " >
< sdk:DataGrid.Columns >
< sdk:DataGridTextColumn Header = " 省会 " Binding = " {Binding AddrName} " IsReadOnly = " True " />
< sdk:DataGridTextColumn Header = " 城市 " Binding = " {Binding CityName} " IsReadOnly = " True " />
< sdk:DataGridTextColumn Header = " 电话区号 " Binding = " {Binding TelNum} " IsReadOnly = " True " />
< sdk:DataGridTemplateColumn Header = " 城市图片 " >
< sdk:DataGridTemplateColumn.CellTemplate >
< DataTemplate >
< Image Source = " {Binding CityImageUrl, Mode=TwoWay, Converter={StaticResource ImageCoverter}} " ></ Image >
</ DataTemplate >
</ sdk:DataGridTemplateColumn.CellTemplate >
</ sdk:DataGridTemplateColumn >
</ sdk:DataGrid.Columns >
</ sdk:DataGrid >
四、为这个DataGrid绑定数据源如下代码:
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
List < CityInformation > listCity = new List < CityInformation > ()
{
new CityInformation(){
AddrName = " 四川 " ,
CityName = " 成都 " ,
TelNum = " 028-28884482 " ,
CityImageUrl = " http://sc.admin5.com/uploads/allimg/100211/105R34217-0.png "
},
new CityInformation()
{
AddrName = " 广东 " ,
CityName = " 广州 " ,
TelNum = " 021-22332884 " ,
CityImageUrl = " http://sc.admin5.com/uploads/allimg/100211/105R333J-4.png "
},
new CityInformation()
{
AddrName = " 上海 " ,
CityName = " 上海 " ,
TelNum = " 020-33245566 " ,
CityImageUrl = " http://sc.admin5.com/uploads/allimg/100211/105R31S6-9.png "
},
new CityInformation()
{
AddrName = " 北京 " ,
CityName = " 北京 " ,
TelNum = " 010-77534222 " ,
CityImageUrl = " http://sc.admin5.com/uploads/allimg/100211/105R33342-7.png "
}
};
this .ShowCityList.ItemsSource = listCity;
}
}
/// <summary>
/// 城市信息的实体类
/// </summary>
public class CityInformation
{
private string _AddrName;
private string _CityName;
private string _TelNum;
private string _cityImageUrl;
public string AddrName
{
get { return _AddrName; }
set { _AddrName = value; }
}
public string CityName
{
get { return _CityName; }
set { _CityName = value; }
}
public string TelNum
{
get { return _TelNum; }
set { _TelNum = value; }
}
public string CityImageUrl
{
get { return _cityImageUrl; }
set { _cityImageUrl = value; }
}
}
思考二:我需要做一个自定义控件,自定义控件是以厘米为单位来设置其宽度,而不是以像素为单位来设置,应该如何实现?
TypeConverter的使用方法:
一、编写一个SLConverter类型继承于TypeConverter类,重写了CanConvertFrom方法和ConvertFrom方法将XAML中的String类型的数据转换为Double类型赋值给自定义控件。
public class CustomLengthConverter : TypeConverter
{
// 返回一个值,该值指示类型转换器能否将指定类型的对象转换为此转换器的类型
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof ( string ))
{
return true ;
}
return base .CanConvertFrom(context, sourceType);
}
// 从指定值转换为此转换器的预期转换类型。
public override object ConvertFrom(ITypeDescriptorContext context, CultureInfo culture, object value)
{
if (value == null )
{
return new Double();
}
if (value is string )
{
string s = ( string )value;
if (s.Length == 0 )
{
return new Double();
}
// 将流入的字符串分割为两部分,使用第一部分2cm*40=80=设置的像素
string [] arguments = s.Split( ' ' );
if (arguments.Length != 2 )
{
return new Double();
}
else
{
// 假设1cm=40px
return InternalParseInput(( double .Parse(arguments[ 0 ]) * 40 ).ToString());
}
}
return base .ConvertFrom(context, culture, value);
}
// 将String数据格式化为Double类型数据返回给属性
public Double InternalParseInput(String inputString)
{
Double doubleValue;
try
{
doubleValue = Double.Parse(inputString);
}
catch (Exception)
{
doubleValue = new Double();
}
return doubleValue;
}
}
public partial class RichTextBlock : UserControl
{
public RichTextBlock()
{
InitializeComponent();
}
[TypeConverter( typeof (CustomLengthConverter))]
public Double txtWidth
{
get { return this .txtBlock.Width; }
set { this .txtBlock.Width = value; }
}
public Double txtHeight
{
get { return this .txtBlock.Height; }
set { this .txtBlock.Height = value; }
}
}
< this :RichTextBlock VerticalAlignment = " Top " txtHeight = " 150 " txtWidth = " 2 cm " />
最后我们来看代码运行的效果图如下,另外如需源码请点击 SLConverter.zip 下载。