WPF中的IValueConverter接口(值转换器)

1.IValueConverter 是什么?解决什么问题?

1.1 定义

IValueConverter是WPF中用于数据绑定时进行值转换的接口。

C# 复制代码
namespace System.Windows.Data
{
    public interface IValueConverter{
        object Convert(object value, Type targetType, object parameter, CultureInfo culture);
        object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
    }
}

当需要调用时,实现该接口并重写Convert和ConvertBack,以下分别叙述这两个方法的用途

1.2 核心作用

当ViewModle中的数据类型,不能直接用View展示,即ViewModel与View对应的数据类型不一致时,需要使用该接口进行数据类型转换,IValueConverter起到了"翻译官"的角色。

2.为什么要使用值转换器?

在 MVVM 模式中:

  • ViewModel 只暴露 业务含义的数据
  • View 需要 UI 能理解的类型

典型示例:

ViewModel数据 View
bool Visibility
enum Style
DataTime string

为了解决这样的类型不匹配,需要使用值转换器

3.IValueConverter 的生命周期与执行时机

3.1 执行时机

IValueConverter的实现类对象会在以下情况被调用

  • 绑定源属性首次赋值
  • 绑定源属性发生变化(INotifyPropertyChanged)
  • 绑定目标需要重新计算显示值

3.2 执行方向

ViewModel -> View 调用Convert方法

View -> ViewModel 调用ConvertBack方法

4.Convert 与 ConvertBack 的职责划分

4.1 Convert

C# 复制代码
object Convert(object value, Type targetType,object parameter, CultureInfo culture);
参数 含义
value 当前传递的值,在Concert中来自ViewModel
targetType 目标属性类型
parameter XAML传入的附加参数
culture 区域信息

4.2CovertBack

C# 复制代码
object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
参数 含义
value 当前传递的值,来自View
targetType 目标属性类型
parameter XAML传入的附加参数
culture 区域信息

一般不具体实现

C# 复制代码
object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture){
    Binding.DoNothing;
}

在以下两种情况需要具体实现

  • Mode=TwoWay
XAML 复制代码
{Binding Path=... Mode=TwoWay}
  • View需要回写到ViewModel中

5.具体实例

需要实现导航栏按钮被按下后,样式改变以提醒用户界面切换,为了完成该需求,可以在ViewModel中维护一个枚举属性来记录当前的访问界面

C# 复制代码
//枚举
```
public enum MainWindowMenuItem
{
    Menu1,
    Menu2,
    Menu3,
    Menu4,
    Menu5,
    Menu6,
    Menu7,
    Menu8,
    Menu9
}
```

public partial class MainWindowViewModel : ObservableObject
{
    ...Other...
    [ObservableProperty] private MainWindowMenuItem _selectedMenuItem = MainWindowMenuItem.Menu1;
    ...Other...
}
XAML 复制代码
<Button
    Style="{Binding SelectedMenuItem,Converter={StaticResource MenuConverter},ConverterParameter={x:Static local:MainWindowMenuItem.Menu1}}"
    Command="{Binding SelectMenuCommand}"
    CommandParameter="{x:Static local:MainWindowMenuItem.Menu1}">
    <Button.Content>
        ...
    </Button.Content>
</Button>

可以看到这个按钮绑定了一个传入枚举的命令,当点击它的时候,他会修改ViewModel中的SelectedMenuItem属性,当该属性被修改时,会把对应的枚举值交给值转换器,然后对比按钮上的parameter,将被点击的按钮的样式修改为SelectedButtonStyle。

C# 复制代码
public class MenuConverter:IValueConverter
{
    public object? Convert(object? value, Type targetType, object? parameter, CultureInfo culture)
    {
        var normal = (Style)Application.Current.Resources["NormalButtonStyle"];
        var selected = (Style)Application.Current.Resources["SelectedButtonStyle"];

        if (value == null || parameter == null)
            return normal;

        return value.Equals(parameter) ? selected : normal;
    }

    public object? ConvertBack(object? value, Type targetType, object? parameter, CultureInfo culture)
    {
        return Binding.DoNothing;
    }
}
相关推荐
上进小菜猪4 小时前
基于 YOLOv8 的昆虫智能识别工程实践 [目标检测完整源码]
后端
superman超哥4 小时前
Rust 异步递归的解决方案
开发语言·后端·rust·编程语言·rust异步递归
开心就好20255 小时前
iOS Crash日志全面解析:结构、类型与分析方法
后端
毕设源码-钟学长5 小时前
【开题答辩全过程】以 基于Spring Boot的社区养老服务管理系统的设计与实现为例,包含答辩的问题和答案
java·spring boot·后端
nbsaas-boot5 小时前
slice / map 在 Go GC 与内存碎片上的真实成本
开发语言·后端·golang
数据小馒头5 小时前
拒绝循环写库:MySQL 批量插入、Upsert 与跨表更新的高效写法
后端
子洋5 小时前
基于远程开发的大型前端项目实践
运维·前端·后端
sheji34165 小时前
【开题答辩全过程】以 基于spring boot的停车管理系统为例,包含答辩的问题和答案
java·spring boot·后端
源代码•宸6 小时前
Leetcode—1266. 访问所有点的最小时间【简单】
开发语言·后端·算法·leetcode·职场和发展·golang
中年程序员一枚6 小时前
多数据源的springboot进行动态连接方案
java·spring boot·后端