【WPF】Binding和MultiBinding数据绑定:Converter的使用(IValueConverter/IMultiValueConverter)

Binding和MultiBinding中存在一个Converter属性,可以用来对绑定的数据进行一些处理后,转换成页面需要的数据。
Converter属性在MultiBinding中使用更加常见,将多个属性值转成UI需要的单个值。

Binding Converter

举例

下面举例同一显示效果的两种写法,来展示Converter的用法

存在需求

下拉框需要满足editType!="不可修改"&&valueType==“Option”条件才能可见,否则都是不可见状态。

常规写法

使用两组MultiDataTrigger来实现
xaml部分

<ComboBox ItemsSource="{Binding valueOptions}"
		  SelectedItem="{Binding selectedOptionItem}">
	<ComboBox.Style>
		<Style TargetType="ComboBox">
			<Setter Property="Visibility" Value="Collapsed"/>
			<Style.Triggers>
				<MultiDataTrigger>
					<MultiDataTrigger.Conditions>
						<Condition  Binding="{Binding valueType}" 
						Value="Option"/>
						<Condition Binding="{Binding editType}" 
						Value="任意修改"/>
					</MultiDataTrigger.Conditions>
					<MultiDataTrigger.Setters>
						<Setter Property="Visibility" Value="Visible"/>
					</MultiDataTrigger.Setters>
				</MultiDataTrigger>
				<MultiDataTrigger>
					<MultiDataTrigger.Conditions>
						<Condition  Binding="{Binding valueType}" 
						Value="Option"/>
						<Condition Binding="{Binding editType}" 
						Value="停机修改"/>
					</MultiDataTrigger.Conditions>
					<MultiDataTrigger.Setters>
						<Setter Property="Visibility" Value="Visible"/>
					</MultiDataTrigger.Setters>
				</MultiDataTrigger>
			</Style.Triggers>
		</Style>
	</ComboBox.Style>
	<ComboBox.ItemTemplate>
		<DataTemplate>
			<TextBlock Text="{Binding fullDetail}"/>
		</DataTemplate>
	</ComboBox.ItemTemplate>
</ComboBox>

cs部分

public string editType{get;set;}
public string valueType{get;set;}
Converter写法

cs部分新增bool类型

public string editType{get;set;}
public string valueType{get;set;}

public bool IsCheckBoxVisibility
{
    get {
        return valueType == ValueTypeEnum.Option && editType != "不可修改";
    }
}

IValueConverter接口的Visibility实现

public class VisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is bool isVisible && isVisible)
        {
            return Visibility.Visible;
        }
        return Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

xaml中使用VisibilityConverter

<UserControl.Resources>
    <local:VisibilityConverter x:Key="VisibilityConverter"/>
</UserControl.Resources>
<ComboBox ItemsSource="{Binding valueOptions}"
          SelectedItem="{Binding selectedOptionItem}"
          Visibility="{Binding IsCheckBoxVisibility,Converter={StaticResource VisibilityConverter}}">
    <ComboBox.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding fullDetail}"/>
        </DataTemplate>
    </ComboBox.ItemTemplate>
</ComboBox>

更多Converter

根据举例可以简单理解Converter的应用场景和优势,同时VisibilityConverter是可以复用的,当同一工程中出现类似的情况,可以复用此Converter。

接下来补充一些常见的Converter

BytesToStringConverter

字节数组转字符串Converter,当我们获取的数据是一串字节数组时,需要将字节数组变成字符串显示要页面上。

<TextBox Text="{Binding Content,Mode=TwoWay,
UpdateSourceTrigger=PropertyChanged, 
Converter={StaticResource BytesToStringConverter}}" />
public byte[] Content{get;set;}

public class BytesToStringConverter : IValueConverter 
{ 
	public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
	{ 
		if (!(value is byte[])) { return null; } 
		byte[] bytes = value as byte[]; 
		string str = System.Text.Encoding.Default.GetString(bytes); 
		return str.ToString(); 
	} 
	public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture) 
	{ 
		if (!(value is string)) { return null; } 
		byte[] bytes = System.Text.Encoding.Default.GetBytes(value as string); 
		return bytes; 
	} 
}
自适应宽度转换器WidthConverter

需要某控件的宽度根据另一控件的宽度变化,如Button宽度是其外面Border宽度的1/3

<Border Name="border" Margin="50" BorderBrush="Black" BorderThickness="2">
	<Button Content="宽是边框的1/3 长=宽"
			Width="{Binding ElementName=border, Path=ActualWidth, 
			Converter={StaticResource widthconverter}}"
			Height="{Binding RelativeSource={RelativeSource Mode=Self}, 
			Path=Width}"></Button>
</Border>
public class WidthConverter : IValueConverter
{
	public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
	{
		// 返回宽度的 1/3
		return (double)value / 3;
	}

	public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
	{
		throw new NotImplementedException();
	}
}

MultiBinding Converter

多重绑定(Multibinding)允许开发者将一个属性绑定到多个源属性。这种绑定通常与转换器(Converter)一起使用,转换器负责将多个源属性的值合并为目标属性可以接受的单个值。

Converter

简单例子

拼接字符串

<TextBlock>
	<TextBlock.Text>
		<MultiBinding Converter="{StaticResource myConverter}">
			<Binding Path="FirstName" />
			<Binding Path="LastName" />
		</MultiBinding>
	</TextBlock.Text>
</TextBlock>
public class NameConverter : IMultiValueConverter
{
	public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
	{
		return $"{values[0]} {values[1]}";
	}
	
	public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
	{
		var fullName = ((string)value).Split(' ');
		return new object[] { fullName[0], fullName[1] };
	}
}

应用

表格中存在一个单元格的背景颜色需要根据值的情况来设置,首先表格每行中存在设定值、当前值和出厂值, 存在修改类型,存在更新状态。
要求设定值所在单元格的背景颜色根据如下情况进行变化。
1、设定值和当前值不同:#FFE4E1;
2、设定值和出厂值不同:#EFE4B0;
3、修改类型为不可修改:#B0B0B0;
4、更新状态为更新失败:#FEC8F1;

<TextBlock.Background>
    <MultiBinding Converter="{StaticResource SetValueBackgroundConverter}">
        <Binding Path="setValue" UpdateSourceTrigger="PropertyChanged" />
        <Binding Path="curValue" UpdateSourceTrigger="PropertyChanged"/>
        <Binding Path="defaultValue" UpdateSourceTrigger="PropertyChanged"/>
        <Binding Path="editType" UpdateSourceTrigger="PropertyChanged"/>
        <Binding Path="updateStatus" UpdateSourceTrigger="PropertyChanged"/>
    </MultiBinding>
</TextBlock.Background>
public class SetValueBackgroundConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        object setValue = values[0];
        object curValue = values[1];
        object defaultValue = values[2];
        string editType = values[3].ToString(); 
        string updateStatus = values[4].ToString();
        if (editType == "不可修改") return new SolidColorBrush((Color)ColorConverter.ConvertFromString("#B0B0B0"));
        if (updateStatus == "更新失败") return new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FEC8F1"));
        if (setValue.ToString() != "--" && setValue.ToString() != curValue.ToString()) return new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FFE4E1"));
        if (setValue.ToString() != "--" && setValue.ToString() != defaultValue.ToString()) return new SolidColorBrush((Color)ColorConverter.ConvertFromString("#EFE4B0"));
        return Binding.DoNothing;
    }

    public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
posted @ 2025-04-14 09:49  Sitar  阅读(226)  评论(0)    收藏  举报