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;
    }
}
相关推荐
Wyy_9527*2 小时前
Spring三种注入方式对比
java·后端·spring
一个大专生的淘汰之路2 小时前
Elasticsearch 中的 term的查询
后端
shepherd1112 小时前
从入门到实践:玩转分布式链路追踪利器SkyWalking
java·后端·架构
小小8程序员2 小时前
springboot + vue
vue.js·spring boot·后端
最贪吃的虎2 小时前
MySQL调优 一:慢SQL日志
运维·数据库·后端·mysql
武子康2 小时前
大数据-192 DataX 3.0 架构与实战:Reader/Writer 插件模型、Job/TaskGroup 调度、speed/errorLimit 配置速
大数据·分布式·后端
用户9446814013503 小时前
JUC 小试牛刀:从源码分析「ArrayBlockingQueue」,Java自带的线程安全的、有界的阻塞队列
java·后端