赞
踩
在基本绑定中,信息从源到目标的传递过程中没有任何变化。这看起来是符合逻辑的,但我们并不总是希望出现这种行为。通常,数据源使用的是低级表达方式,我们可能不希望直接在用户界面使用这种低级表达方式。WPF提供了两个工具,来进行数据转换:
字符串格式化
通过设置 Binding.StringFormat 属性对文本形式的数据进行转换——例如包含日期和数字的字符串。
值转换器
该功能更强大,使用该功能可以将任意类型的源数据转换为任意类型的对象表示,然后可以传递到关联的控件。
使用StringFormat属性
- <TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Path=Price, StringFormat=ConvertDirectly:{0:C}}"></TextBlock>
- <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=Price, StringFormat={}{0:C}}"></TextBox>
- <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Path=OrderDate, StringFormat={}{0:s}}"></TextBox>
可以看到后面两个StringFormat属性以花括号 {} 开头,完整值是 {}{0:C},而不是 {0:C},第一个则只有 {0:C},这是因为在StringFormat 值以花括号开头时需要 {} 转义序列。
使用值转换器
为创建子转换器需要执行以下四个步骤:
1、创建一个实现IValueConverter接口的类
2、为该类声明添加ValueConversion特性,并指定目标数据类型
3、实现Convert()方法,该方法将数据从原来的格式转换为显示的格式
4、实现ConvertBack()方法,该方法执行反向变换,将值从显示格式转换为原格式
- [ValueConversion(typeof(decimal), typeof(string))]
- public class PriceConverter : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- decimal price = (decimal)value;
- return price.ToString("C", culture);
- }
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- string price = (string)value;
- if (decimal.TryParse(price, System.Globalization.NumberStyles.Any, culture, out decimal result))
- {
- return result;
- }
- return value;
- }
- }
要使用这个转换器,可以将其添加到页面的资源下,然后使用 Binding.Converter 指定。
- <Window>
- <Window.Resources>
- <local:PriceConverter x:Key="priceConverter"/>
- <local:PriceToBackgroundConverter x:Key="priceToBackgroundConverter" MinimumPriceToHighlight="100" DefaultBrush="{x:Null}" HighlightBrush="Orange"/>
- <local:ImagePathConverter x:Key="imagePathConverter"/>
- <local:MultiValueConverter x:Key="multiValueConverter"/>
- </Window.Resources>
- <TextBox Text="{Binding Path=Price, Converter={StaticResource priceConverter}}"></TextBox>
- </Window>
多重绑定
可以将多个字段绑定到同一个输出控件,可以通过 StringFormat 或 MultiBinding.Converter 来格式化数据。多重绑定的值转换器需要实现的接口是 IMultiValueConverter,与 IValueConverter 接口比较类似,只是转换函数的第一个参数改成了数组形式。
- <TextBlock Grid.Row="4" Grid.Column="0">
- <TextBlock.Text>
- <MultiBinding StringFormat="{}{0}, {1}, {2}">
- <Binding Path="Price"/>
- <Binding Path="OrderDate"/>
- <Binding Path="Volume"/>
- </MultiBinding>
- </TextBlock.Text>
- </TextBlock>
- <TextBlock Grid.Row="5" Grid.Column="0">
- <TextBlock.Text>
- <MultiBinding Converter="{StaticResource multiValueConverter}">
- <Binding Path="Price"/>
- <Binding Path="Volume"/>
- </MultiBinding>
- </TextBlock.Text>
- </TextBlock>
- public class MultiValueConverter : IMultiValueConverter
- {
- public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- decimal price = (decimal)values[0];
- int volume = (int)values[1];
- return (price * volume).ToString("C");
- }
- public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
- {
- throw new NotSupportedException();
- }
- }
完整代码如下:
MainWindow.xaml
- <Window x:Class="TestDataConverter.MainWindow"
- xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
- xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
- xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
- xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
- xmlns:local="clr-namespace:TestDataConverter"
- mc:Ignorable="d"
- Title="MainWindow" Height="450" Width="800">
- <Window.Resources>
- <local:PriceConverter x:Key="priceConverter"/>
- <local:PriceToBackgroundConverter x:Key="priceToBackgroundConverter" MinimumPriceToHighlight="100" DefaultBrush="{x:Null}" HighlightBrush="Orange"/>
- <local:ImagePathConverter x:Key="imagePathConverter"/>
- <local:MultiValueConverter x:Key="multiValueConverter"/>
- </Window.Resources>
- <Grid Name="myGrid" Background="{Binding Path=Price, Converter={StaticResource priceToBackgroundConverter}}">
- <Grid.ColumnDefinitions>
- <ColumnDefinition/>
- <ColumnDefinition/>
- </Grid.ColumnDefinitions>
- <Grid.RowDefinitions>
- <RowDefinition/>
- <RowDefinition/>
- <RowDefinition/>
- <RowDefinition/>
- <RowDefinition/>
- <RowDefinition/>
- </Grid.RowDefinitions>
-
- <TextBlock Grid.Row="0" Grid.Column="0" Text="{Binding Path=Price, StringFormat=ConvertDirectly:{0:C}}"></TextBlock>
- <TextBox Grid.Row="0" Grid.Column="1" Text="{Binding Path=Price, StringFormat={}{0:C}}"></TextBox>
-
- <TextBlock Grid.Row="1" Grid.Column="0">ConvertWithConverter:</TextBlock>
- <TextBox Grid.Row="1" Grid.Column="1" Text="{Binding Path=Price, Converter={StaticResource priceConverter}}"></TextBox>
-
- <TextBlock Grid.Row="2" Grid.Column="0">ConvertDateTime:</TextBlock>
- <TextBox Grid.Row="2" Grid.Column="1" Text="{Binding Path=OrderDate, StringFormat={}{0:s}}"></TextBox>
-
- <TextBlock Grid.Row="3" Grid.Column="0">ConvertImagePath:</TextBlock>
- <Image Grid.Row="3" Grid.Column="1" Stretch="None" HorizontalAlignment="Left" Source="{Binding Path=Image, Converter={StaticResource imagePathConverter}}"></Image>
-
- <TextBlock Grid.Row="4" Grid.Column="0">
- <TextBlock.Text>
- <MultiBinding StringFormat="{}{0}, {1}, {2}">
- <Binding Path="Price"/>
- <Binding Path="OrderDate"/>
- <Binding Path="Volume"/>
- </MultiBinding>
- </TextBlock.Text>
- </TextBlock>
- <TextBlock Grid.Row="5" Grid.Column="0">
- <TextBlock.Text>
- <MultiBinding Converter="{StaticResource multiValueConverter}">
- <Binding Path="Price"/>
- <Binding Path="Volume"/>
- </MultiBinding>
- </TextBlock.Text>
- </TextBlock>
- </Grid>
- </Window>
MainWindow.xaml.cs
- using System;
- using System.Collections.Generic;
- using System.ComponentModel;
- using System.Globalization;
- using System.IO;
- using System.Runtime.CompilerServices;
- using System.Windows;
- using System.Windows.Controls;
- using System.Windows.Data;
- using System.Windows.Media;
- using System.Windows.Media.Imaging;
-
- namespace TestDataConverter;
-
- public class ViewModelBase : INotifyPropertyChanged
- {
- public event PropertyChangedEventHandler? PropertyChanged;
- protected virtual void OnPropertyChanged([CallerMemberName] string? propertyName = null)
- {
- PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
- }
- protected virtual bool SetProperty<T>(ref T member, T value, [CallerMemberName] string? propertyName = null)
- {
- if (EqualityComparer<T>.Default.Equals(member, value))
- {
- return false;
- }
- member = value;
- OnPropertyChanged(propertyName);
- return true;
- }
- }
-
- public class Order : ViewModelBase
- {
- public decimal price = 0;
- public decimal Price { get => price; set => SetProperty(ref price, value); }
- public int volume = 0;
- public int Volume { get => volume; set => SetProperty(ref volume, value); }
-
- public DateTime orderDate = DateTime.Now;
- public DateTime OrderDate { get => orderDate; set => SetProperty(ref orderDate, value); }
-
- public string image = string.Empty;
- public string Image { get => image; set => SetProperty(ref image, value); }
- }
- [ValueConversion(typeof(decimal), typeof(string))]
- public class PriceConverter : IValueConverter
- {
- public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
- {
- decimal price = (decimal)value;
- return price.ToString("C", culture);
- }
- public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
- {
- string price = (string)value;
- if (decimal.TryParse(price, System.Globalization.NumberStyles.Any, culture, out decimal result))
- {
- return result;
- }
- return value;
- }
- }
- [ValueConversion(typeof(decimal), typeof(Brush))]
- public class PriceToBackgroundConverter : IValueConverter
- {
- public decimal MinimumPriceToHighlight { get; set; }
- public Brush HighlightBrush { get; set; }
- public Brush DefaultBrush { get; set; }
-
- public object Convert(object value, Type targetType, object parameter,
- System.Globalization.CultureInfo culture)
- {
- decimal price = (decimal)value;
- if (price >= MinimumPriceToHighlight)
- return HighlightBrush;
- else
- return DefaultBrush;
- }
- public object ConvertBack(object value, Type targetType, object parameter,
- System.Globalization.CultureInfo culture)
- {
- throw new NotSupportedException();
- }
- }
- public class ImagePathConverter : IValueConverter
- {
- private string imageDirectory = Directory.GetCurrentDirectory();
- public string ImageDirectory
- {
- get { return imageDirectory; }
- set { imageDirectory = value; }
- }
- public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- string imagePath = Path.Combine(ImageDirectory, (string)value);
- return new BitmapImage(new Uri(imagePath));
- }
- public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- throw new NotSupportedException("The method or operation is not implemented.");
- }
- }
- public class MultiValueConverter : IMultiValueConverter
- {
- public object Convert(object[] values, Type targetType, object parameter, System.Globalization.CultureInfo culture)
- {
- decimal price = (decimal)values[0];
- int volume = (int)values[1];
- return (price * volume).ToString("C");
- }
- public object[] ConvertBack(object value, Type[] targetTypes, object parameter, System.Globalization.CultureInfo culture)
- {
- throw new NotSupportedException();
- }
- }
-
- public partial class MainWindow : Window
- {
- public MainWindow()
- {
- InitializeComponent();
- myGrid.DataContext = Order;
-
- Order.Price = 100;
- Order.Volume = 10;
- Order.OrderDate = DateTime.Now;
- Order.Image = "image1.gif";
- }
- public Order Order = new Order();
-
- private void Button_Click(object sender, RoutedEventArgs e)
- {
- Console.WriteLine("");
- }
- }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。