【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; }
        }
    }

 

posted @ 2022-07-17 22:31  小林野夫  阅读(648)  评论(0编辑  收藏  举报
原文链接:https://www.cnblogs.com/cdaniu/