WPF Binding值转换器ValueConverter

本文介绍了如何在WPF、Silverlight及WindowsPhone程序开发中利用.NET Framework提供的单值和多值转换器接口,实现特定的数据转换需求,包括日期格式转换及基于多个绑定值的复杂转换。


单值转换器:猛击这里下载源代码

多值转换器:猛击这里下载源代码

WPF、Silverlight及Windows Phone程序开发中往往需要将绑定的数据进行特定转换,比如DateTime类型的时间转换为yyyyMMdd的日期,再如有一个值是根据另外多组值的不同而异的,此时我们就需要定制自己的Converter。.Net Framework提供了两种Converter接口,单值转换的接口IValueConverter和多值转换的接口IMultiValueConverter,它们都属于System.Windows.Data命名空间,在程序集PresentationFramework.dll中。这两种值转换器都是分区域性的。其中方法Convert和ConvertBack都具有指示区域性信息的culture参数。如果区域性信息与转换无关,那么在自定义转换器中可以忽略该参数。

单值转换器

将单一值转换为特定类型的值,以日期转换为例如下:

1、定制DateConverter类,其中当值从绑定源传播给绑定目标时,调用方法Convert。 

2 、IValueConverter 类在System.Windows.Data空间下。

复制代码
 1     public class DateConverter : IValueConverter
 2     {
 3         public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
 4         {
 5             return ((DateTime)value).ToString("yyyy/MM/dd");
 6         }
 7 
 8         public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
 9         {
10             return null;
11         }
12     }
复制代码

当值从绑定目标传播给绑定源时,调用此方法ConvertBack,方法ConvertBack的实现必须是方法Convert的反向实现。例如下:

复制代码
 1     public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
 2     {
 3         DateTime date = (DateTime)value;
 4         return date.ToShortDateString();
 5     }
 6 
 7     public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
 8     {
 9         string strValue = value as string;
10         DateTime resultDateTime;
11         if (DateTime.TryParse(strValue, out resultDateTime))
12         {
13             return resultDateTime;
14         }
15         return DependencyProperty.UnsetValue;
16     }
复制代码

返回值DependencyProperty.UnsetValue表示转换器没有生成任何值。但是通常情况下方法ConvertBack没有方法Convert常用,这里不做过多介绍。

2、在xmal文件引用DateConverter类所在命名空间。

1         xmlns:cvt="clr-namespace:ValueConverterDemo.Converter"

3、在xaml文件添加Resources。

1     <Window.Resources>
2         <cvt:DateConverter x:Key="cvtDate"/>
3     </Window.Resources>

4、在xaml文件中指定Binding值的Converter

1 Text="{Binding CurrentDate, Converter={StaticResource cvtDate}}"

效果如下图,图中“时间”是未经过转换的原始DateTime类型,“日期”经过转换处理后只显示日期部分。

    

多值转换器

将多组值转换为特定类型的值,以纵横流量影响交通指示灯颜色的变化为例如下:

当纵向流量大于横向流量时指示灯应为绿色,当纵向流量小于横向流量时指示灯应为红色,否则指示灯为黄色。

1、定制ColorConverter类,此时Convert中参数是object[] values,values[0]对应MultiBinding中的第一个Binding值,这里是纵向流量值,依此类推,可以在MultiBinding对象中指定多个绑定。

复制代码
 1     public class ColorConverter : IMultiValueConverter
 2     {
 3         public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
 4         {
 5             double verValue = (double)values[0];
 6             double horValue = (double)values[1];
 7             if (verValue > horValue)
 8             {
 9                 return new SolidColorBrush(Colors.Green);
10             }
11             else if (verValue < horValue)
12             {
13                 return new SolidColorBrush(Colors.Red);
14             }
15             return new SolidColorBrush(Colors.Yellow);
16         }
17 
18         public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
19         {
20             return null;
21         }
22     }
复制代码

2、3步同单值转换。

4、xmal文件中指定定制的Converter,此时需要使用的MultiBinding来指定多组Binding。

1                 <MultiBinding Converter="{StaticResource cvtColor}">
2                     <Binding Path="Value" ElementName="slVer"/>
3                     <Binding Path="Value" ElementName="slHor"/>
4                 </MultiBinding>

效果如下图交通灯的颜色是根据纵向流量和横向流量的关系而变化的。

  • 纵向流量大于横向流量

    

  • 纵向流量小于横向流量

    

  • 纵向流量等于横向流量

    



本文来自cnblogs的博客,原文地址:http://www.cnblogs.com/horan/archive/2012/02/27/2368262.html



<think>我们正在处理一个WPF中的DataGridComboBoxColumn问题。用户希望在DataGridComboBoxColumn中显示字符串,但绑定的值是一个数字(例如,数据库中的外键),而用户选择后需要将选中的字符串转换为对应的数字存储。 根据引用[1]和[2],我们知道DataGridComboBoxColumn的使用方法。但是,默认情况下,如果我们直接绑定SelectedItemBinding到数字属性,由于ComboBox的ItemsSource是字符串列表,因此无法直接绑定。我们需要一个转换机制。 解决方案通常有两种: 1. 使用ValueConverter值转换器)在绑定中进行转换。 2. 创建一个包含字符串和数字的类(例如KeyValuePair),然后将ItemsSource绑定到一个这样的对象列表,然后使用SelectedValueBinding和SelectedValuePath。 根据用户的需求,他们可能已经有一个字符串列表(显示值)和一个对应的数字列表(实际值),或者需要将字符串映射为数字。 方法一:使用ValueConverter(推荐) 我们可以创建一个IValueConverter,将字符串转换为数字(根据映射关系),反之亦然。但是,这里有一个问题:转换器需要知道字符串和数字的对应关系。因此,我们可以在转换器中硬编码映射关系,或者将映射关系传递给转换器(通过ConverterParameter可能不够,因为映射可能比较复杂)。所以,更常见的是方法二。 方法二:使用SelectedValueBinding和SelectedValuePath 这种方法更常见,也是WPF中处理这类问题的标准做法。具体步骤如下: - 定义一个类,包含两个属性:一个是显示字符串(Display),一个是实际值(Value)。 - 将DataGridComboBoxColumn的ItemsSource绑定到一个这样的对象集合(例如List<MyItem>)。 - 设置DisplayMemberPath="Display" - 设置SelectedValuePath="Value" - 设置SelectedValueBinding到数据对象的数字属性。 例如: 假设我们有一个数据对象Employee,它有一个DepartmentId属性(整数),我们希望在ComboBox中显示部门名称(字符串),但存储的是DepartmentId。 步骤: 1. 创建一个类(可以在ViewModel中): public class Department { public int Id { get; set; } public string Name { get; set; } } 2. 在ViewModel中,定义一个部门列表(假设从数据库获取): public List<Department> Departments { get; } = new List<Department> { new Department { Id=1, Name="HR" }, new Department { Id=2, Name="IT" } }; 3. 在DataGridComboBoxColumn中设置: <DataGridComboBoxColumn Header="Department" SelectedValueBinding="{Binding DepartmentId}" DisplayMemberPath="Name" SelectedValuePath="Id" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}, Path=DataContext.Departments}" /> 注意:这里ItemsSource的绑定路径取决于你的数据上下文。如果DataGrid的DataContext是ViewModel,并且ViewModel有Departments属性,那么可以像上面这样绑定。但是,在DataGrid的列中,由于列不在可视化树中,不能直接继承DataGrid的DataContext。因此,我们需要使用RelativeSource来找到DataGrid的DataContext。 但是,根据引用[3](一篇博客文章),我们知道DataGrid的列不能直接继承DataGrid的DataContext。因此,我们需要通过其他方式传递。常见的做法有两种: a) 将列的资源绑定到DataGrid的DataContext(通过RelativeSource),如上例所示。 b) 将Departments集合作为资源放在窗口或用户控件级别,然后通过StaticResource绑定。 如果方法二中遇到绑定问题(因为列不是可视化树的一部分),我们可以参考引用[3]中提到的解决方案:将DataGrid的DataContext传递给列。我们可以使用RelativeSource绑定到DataGrid的DataContext,如上例所示。 如果用户坚持使用字符串列表并且希望转换为数字,那么我们需要一个转换器。但是,转换器需要知道每个字符串对应的数字,所以我们需要一个字典来存储映射关系。然后,在转换器中实现这个字典的查找。这种方法不够灵活,特别是当字符串列表可能变化时。 因此,我们推荐方法二,即使用一个包含显示字符串和实际值的类。 下面给出一个完整的XAML示例(假设DataGrid的DataContext已经设置为包含Departments属性和Employee集合的ViewModel): ```xml <Window ...> <Window.Resources> <!-- 这里可以定义资源,但为了简单,我们直接在列中绑定 --> </Window.Resources> <Grid> <DataGrid x:Name="dataGrid" ItemsSource="{Binding Employees}" AutoGenerateColumns="False"> <DataGrid.Columns> <!-- 其他列 --> <DataGridComboBoxColumn Header="Department" SelectedValueBinding="{Binding DepartmentId}" DisplayMemberPath="Name" SelectedValuePath="Id" ItemsSource="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=DataGrid}, Path=DataContext.Departments}" /> </DataGrid.Columns> </DataGrid> </Grid> </Window> ``` 注意:上面的绑定中,ItemsSource绑定到DataGrid的DataContext的Departments属性。因此,ViewModel必须有一个名为Departments的属性,并且是Department对象的集合。 另外,如果DataGrid的DataContext没有Departments属性,或者我们在其他上下文中,可能需要调整绑定路径。 如果用户的问题中已经有一个字符串列表,并且有一个对应的数字列表,那么我们可以动态构建一个Department列表(将字符串列表和数字列表组合)。例如: var stringList = new List<string> { "HR", "IT" }; var intList = new List<int> { 1, 2 }; Departments = stringList.Zip(intList, (s, i) => new Department { Name = s, Id = i }).ToList(); 最后,我们也可以考虑使用DataGridTemplateColumn并自定义ComboBox模板,这样更灵活,但代码稍多。 因此,总结解决方案: 推荐使用DataGridComboBoxColumn的SelectedValueBinding配合SelectedValuePath和DisplayMemberPath,并将ItemsSource绑定到一个包含显示文本和实际值的对象集合。 相关问题: 1. 如果在DataGridComboBoxColumn中绑定ItemsSource时遇到空引用,如何调试? 2. 如何动态更新DataGridComboBoxColumn的下拉列表(例如,根据其他列的值改变可选列表)? 3. 在DataGridComboBoxColumn中如何实现搜索或过滤功能? </think>### WPF中将DataGridComboBoxColumn字符串选择值转换为数字的解决方案 在WPF中实现`DataGridComboBoxColumn`的字符串选择值到数字的转换,核心是通过**数据绑定**配合以下两种方式实现: #### ✅ 方法一:使用值转换器ValueConverter) 1. **创建字符串-数字映射的转换器**: ```csharp public class StringToIntConverter : IValueConverter { public object Convert(object value, Type targetType, object parameter, CultureInfo culture) { // 数字转字符串(用于显示) return value switch { 1 => "HR", 2 => "IT", _ => "Unknown" }; } public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture) { // 字符串转数字(用于存储) return (string)value switch { "HR" => 1, "IT" => 2, _ => 0 }; } } ``` 2. **在XAML中应用转换器**: ```xml <Window.Resources> <local:StringToIntConverter x:Key="StringIntConverter"/> </Window.Resources> <DataGridComboBoxColumn Header="部门" ItemsSource="{Binding Source={StaticResource DepartmentOptions}}" <!-- 字符串列表 --> SelectedItemBinding="{Binding DepartmentId, Converter={StaticResource StringIntConverter}}"/> <!-- 绑定到数字属性 --> ``` #### ✅ 方法二:使用SelectedValuePath(推荐) 1. **创建中间数据类**: ```csharp public class DepartmentOption { public int Id { get; set; } // 存储的数字值 public string Name { get; set; } // 显示的字符串 } ``` 2. **配置DataGridComboBoxColumn**: ```xml <DataGridComboBoxColumn Header="部门" DisplayMemberPath="Name" <!-- 显示字符串 --> SelectedValuePath="Id" <!-- 实际存储值 --> SelectedValueBinding="{Binding DepartmentId}" <!-- 绑定到数字属性 --> ItemsSource="{Binding RelativeSource={RelativeSource AncestorType=DataGrid}, Path=DataContext.AllDepartments}"/> <!-- 绑定选项列表 --> ``` #### 📌 关键说明 1. **ItemsSource**:绑定到`List<DepartmentOption>`集合(包含Id和Name属性) 2. **SelectedValuePath**:指定数字属性(如`Id`) 3. **SelectedValueBinding**:直接绑定到数据模型的数字字段 4. **数据上下文**:通过`RelativeSource`解决列继承问题[^3] > 推荐使用**方法二**,符合WPF数据绑定规范,避免手动维护映射关系,且支持动态更新选项列表[^2]。 --- ###
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值