【WPF】IvalueConverter和TypeConverter类型转换器的实现
原文:https://www.cnblogs.com/tt2015-sz/p/4744181.html
简要说明
IValueConverter主要用于XAML绑定和数据源之间的转换
TypeConverter主要用于自定义类的属性类型之间的转换
本文主要讲解如何使用IValueConverter和TypeConverter。我们通过两个思考问题来引入如何使用IValueConverter和TypeConverter!
IValueConverter主要用于将数据源的数据转换为需要在界面上显示的数据,例如:将Url地址转换为图片显示到界面上、将float类型数据显示为货币类型、bool值和Visibility转换等等
TypeConverter主要用于在XAML代码中的字符串类型转换为其他类型的数值,比如将一段字符串转为Double类型以供Width属性使用
类型转换器提供字符串文本到值的转换方法来帮助WPF设计时在XAML中配置属性。具体用法可以参考MSDN的文档:如何:实现类型转换器。
TypeConverter类型转换器
下面是一个Demo,参考自<葵花宝典--WPF自学手册>。
1、MainWindow.xaml
<Window x:Class="WpfApplication1.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:sys="clr-namespace:System;assembly=mscorlib" xmlns:local="clr-namespace:WpfApplication1" Title="MainWindow" Height="350" Width="525"> <DockPanel HorizontalAlignment="Left" Height="322" LastChildFill="False" VerticalAlignment="Top" Width="515" Margin="0,0,0,-2"> <Button DockPanel.Dock="Left" Background="AliceBlue" Width="264"> <local:Book Name="CookBook" Price="$0.1"> 内容:梦里花落知多少 </local:Book> </Button> <Button DockPanel.Dock="Right" Width="249"> <Button.Background> <LinearGradientBrush StartPoint="0,0" EndPoint="1,1"> <GradientStop Color="Yellow" Offset="0.0"/> <GradientStop Color="Aquamarine" Offset="0.25"/> <GradientStop Color="Bisque" Offset="0.75"/> <GradientStop Color="Coral" Offset="1.0"/> </LinearGradientBrush> </Button.Background> Hello XAML </Button> </DockPanel> </Window>
第一个Button的Content属性的值设置成一个自定义的Book类,该Book对象调用ToString()方法返回的字符串就会显示在Button上,注意该Book对象的Price属性设置为"$0.1",即0.1美元,通过类型转换器,将会把这个值转换为"0.8"(人民币)。
第二个Button使用了渐变画刷来设置背景。
2、Book.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
//ContenProperty所在的命名空间
using System.Windows.Markup;
namespace WpfApplication1
{
[ContentProperty("Text")] //声明Content属性
public class Book
{
public Book()
{
}
//Name属性
public string Name
{
get;
set;
}
//Price属性的数据类型是一个MoneyType类,该类声明了类型转换器,可以将带有美元符号的价格转换为人民币
public MoneyType Price
{
get;
set;
}
//Text属性
public string Text { get; set; }
public override string ToString()
{
string str = Name + "售价为:" + Price + "元\n"+Text;
return str;
}
}
}
Book类中声明了三个自动属性,其中将Text属性声明为ContentProperty,这样不必使用Property-Element语法就可以直接成为Button元素的子类;Price属性是MoneyType类型,该类声明了一个类型转换器,可以将美元转换为人民币。
3、MoneyType.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//TypeConverter所在的命名空间
using System.ComponentModel;
namespace WpfApplication1
{
//声明类型转换器
[TypeConverter(typeof(MoneyConverter))]
public class MoneyType
{
private double _value;
public MoneyType() { _value = 0; }
public MoneyType(double value)
{
_value = value;
}
public override string ToString()
{
return _value.ToString();
}
//价格转换方法,这里只考虑美元和人民币,不考虑其他币种
public static MoneyType Parse(string value)
{
string str = (value as string).Trim();
if (str[0] == '$')
{
//将美元转换为人民币
string newprice = str.Remove(0, 1);
double price = double.Parse(newprice);
return new MoneyType(price * 8);
}
else
{
//不带特殊符号的字符串默认识别为人民币
double price = double.Parse(str);
return new MoneyType(price);
}
}
}
}
MoneyType类中声明了类型转换器,并且实现了一个类方法Parse(),在该方法中完成对字符串的转换。
4、MoneyConverter.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//TypeConverter所在的命名空间
using System.ComponentModel;
namespace WpfApplication1
{
public class MoneyConverter : TypeConverter
{
public override bool CanConvertFrom(ITypeDescriptorContext context, Type sourceType)
{
if (sourceType == typeof(string))
return true;
return base.CanConvertFrom(context, sourceType);
}
//转换为字符串类型其实不需要重写此方法
public override bool CanConvertTo(ITypeDescriptorContext context, Type destinationType)
{
if (destinationType == typeof(string))
{
return true;
}
return base.CanConvertTo(context, destinationType);
}
//将string转换为MoneyType
public override object ConvertFrom(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value)
{
if (value is string)
return MoneyType.Parse((string)value);
return base.ConvertFrom(context, culture, value);
}
//将MoneyType转换为string
public override object ConvertTo(ITypeDescriptorContext context, System.Globalization.CultureInfo culture, object value, Type destinationType)
{
if (destinationType == typeof(string))
{
return ((MoneyType)value).ToString();
}
return base.ConvertTo(context, culture, value, destinationType);
}
}
}
这个类型转换器实现了string和MoneyType的相互转换。
5、运行效果
IValueConverter类型转换器
思考一:我的数据集合的其中一个集合中的属性为某个图片的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的资源中申明ImageConverter以供DataGrid的数据源绑定时转换数据
<UserControl.Resources> <this:ImageConverter x:Key="ImageCoverter"/> </UserControl.Resources>
三、在DataGrid中使用Converter转换,代码如下:
<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; } } }