当前位置: 首页 > news >正文

WPF数据转换

在基本绑定中,信息从源到目标的传递过程中没有任何变化。这看起来是符合逻辑的,但我们并不总是希望出现这种行为。通常,数据源使用的是低级表达方式,我们可能不希望直接在用户界面使用这种低级表达方式。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;elsereturn 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("");}
}

http://www.lryc.cn/news/146008.html

相关文章:

  • 《Go 语言第一课》课程学习笔记(十三)
  • 基于RUM高效治理网站用户体验入门-价值篇
  • Unity之Photon PUN2开发多人游戏如何实现组队功能
  • 大数据Flink简介与架构剖析并搭建基础运行环境
  • RISC-V IOPMP实际用例-Rapid-k模型在NVIDIA上的应用
  • 【UE5】给模型指定面添加自定义材质
  • mall:redis项目源码解析
  • RISC-V Linux系统kernel制作
  • 5G NR:PRACH时域资源
  • LLaMA-2的模型架构
  • 掌握Java框架之Struts,开启高效开发之旅!
  • 关于Vue.set()
  • Selenium 遇见伪元素该如何处理?
  • RPA技术介绍与应用价值
  • 产品经理,需要具备哪些能力和知识
  • 【C++】map和set
  • crawlab通过docker单节点部署简单爬虫
  • 【STM32】中断与NVIC以外部中断为例
  • 大学生网页设计制作作业实例代码 (全网最全,建议收藏) HTML+CSS+JS
  • Llama模型结构解析(源码阅读)
  • 基于XML实现SpringIoC配置
  • Kaniko在containerd中无特权快速构建并推送容器镜像
  • 分享5款不会被打入冷宫的神器软件
  • Windows如何部署Redis
  • VUE数据双向绑定原理解析
  • SSM商城项目实战:订单管理
  • SELinux 入门 pt.2
  • 函数(个人学习笔记黑马学习)
  • 《Flink学习笔记》——第五章 DataStream API
  • Vue3.0 新特性以及使用变更总结