WPF 属性值绑定、转换

TextBlock绑定属性

绑定集合中的第一项的属性

<TextBlock Text="{Binding [1].PropertyName1}" DataContext="{Binding DemoList}"/>

绑定单个属性及转换器

<UserControl.Resources>
    <cvt:StateConv x:Key="stateConv"/>
</UserControl.Resources>
...
<TextBlock Text="{Binding Name, StringFormat={}{0:F2}, Converter="{StaticResource stateConv}"}"/>
using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
public class StateConv: IValueConverter
{
    // 此文本将显示在控件中(比如:TextBox)
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        int type = 0;
        if (int.TryParse(value.ToString(), out type))
        {
            if (type == 1) { return "正常"; }
            else { return "异常"; }   
        } 
        return DependencyProperty.UnsetValue;                          
    }
    // 目标数据格式转换为原数据格式(正常->1)
    // 当您更改控件TextBox的值时,ConvertBack方法将在绑定再次触发时调用(默认OnFocusLost)
    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (string.IsNullOrEmpty(value?.ToString()))
                return -1;
            
        var item = TypeResource.FirstOrDefault(x => x.DisplayText == value.ToString());
        if (item == null)
        {
           return -1;
        }
        return item.Key;
    }
}

转换器2

数值转换,显示指定枚举类型的文本描述

public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
{
    if (value != null && int.TryParse(value.ToString(), out int type))
    {
        if (Enum.IsDefined(typeof(PropertyNameEnumType), type))
        {
            var @enum = (PropertyNameEnumType)type;
            return @enum.GetEnumDescription();
        }
    }
    return "未知状态";
}

多重绑定1

<Label.Content>
    <TextBlock>
	<TextBlock.Text>
		<MultiBinding StringFormat="{}{0}({1})">
			<Binding Path="Name1" TargetNullValue="用默认值来显示为空的字段" />
			<Binding Path="Name2" />
		</MultiBinding>
	</TextBlock.Text>
    </TextBlock>
</Label.Content>

StringFormat要求它的目标是string类型。 可在指定控件内嵌套TextBlock进行自定义格式转换。
若要体现动态数据,属性所属类需要实现INotificationPropertyChanged接口,绑定的属性可以响应属性更改事件。

多重绑定2

<UserControl.Resources>
    <cvt:MultiStateConv x:Key="multiStateConverter"/>
    <cvt:MultiVersionTypeConv x:Key="multiVersionTypeConverter"/>
</UserControl.Resources>
...
<TextBlock>
    <TextBlock.Text>
        <MultiBinding Converter="{StaticResource multiStateConverter}" ConverterParameter="{StaticResource bindingProxy}">
            <Binding Path="Name"/>
            <Binding Path="Name2"/>
            <!--绑定父级属性 PropertyName2-->
            <Binding Path="DataContext.PropertyName2" RelativeSource="{RelativeSource AncestorLevel=2, AncestorType={x:Type ListBoxItem}}"/>
        </MultiBinding>
    </TextBlock.Content>
</TextBlock>

<DataGridTextColumn Header="版本类型" Width="*">
    <DataGridTextColumn.Binding>
        <MultiBinding Converter="{StaticResource multiVersionTypeConverter}" ConverterParameter="{StaticResource multiStateConverter}">
            <Binding Path="Type1"/>
            <Binding Path="Type2"/>
        </MultiBinding>
    </DataGridTextColumn.Binding>
</DataGridTextColumn>
using System;
using System.Globalization;
using System.Windows.Data;

[ValueConversion(typeof(object[]), typeof(string))]
class MultiStateConv : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        var cvt = parameter as MultiStateConv;
        string rslt = string.Empty;
        if (int.TryParse(values[0].ToString(), out int type))
        {
            //...             
        }
        if (int.TryParse(values[1].ToString(), out int type2))
        {
            //...
        }
        return rslt;                           
    }

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

多重绑定3

当传递的参数过多时,可以使用绑定代理。
当显示逻辑比较复杂时,有多个参数规则,可重复设置同样内容,并控制不同的显隐来实现。

xmlns:cvt="clr-namespace:ProjectName.Converters" 

<Color x:Key="Color1">#FF4E5E</Color>
<SolidColorBrush x:Key="Brush1" Color="{DynamicResource Color1}"/>
<cvt:BindingProxy x:Key="bindingProxy" Data="{DynamicResource Brush1}" Reserve="{DynamicResource 3thDllBrush}" Thread="10.0"/>

<cvt:ExceptionValueConv x:Key="exceptionValueConveter"/>
<cvt:ExceptionForegroundVisibleConv x:Key="exceptionForegroundVisibleConveter"/>
<cvt:ExceptionForegroundReVisibleConv x:Key="exceptionForegroundReVisibleConveter"/>

<Grid>
    <TextBlock Foreground="{DynamicResource Brush3}"
               Visibility="{Binding Percent, Converter={StaticResource exceptionForegroundVisibleConveter}, ConverterParameter={StaticResource bindingProxy}}">
        <Run Text="{Binding Percent, StringFormat={}{0:f1}, Converter={StaticResource exceptionValueConveter}}" />
        <Run Text="%"/>
    </TextBlock>
    <!--同样内容-->
    <TextBlock Foreground="{DynamicResource Brush4}"
               Visibility="{Binding Percent, Converter={StaticResource exceptionForegroundReVisibleConveter}, ConverterParameter={StaticResource bindingProxy}}"> 
        <Run Text="{Binding Percent, StringFormat={}{0:f1}, Converter={StaticResource exceptionValueConveter}}" />
        <Run Text="%"/>
    </TextBlock>
</Grid>


using System.Windows;

internal class BindingProxy : Freezable
{
    protected override Freezable CreateInstanceCore()
    {
        return new BindingProxy();
    }

    /// <summary>
    /// 原始数据
    /// </summary>
    public object Data
    {
        get { return (object)GetValue(DataProperty); }
        set { SetValue(DataProperty, value); }
    }
    public static readonly DependencyProperty DataProperty = DependencyProperty.Register("Data", typeof(object), typeof(BindingProxy), new PropertyMetadata(null));

    /// <summary>
    /// 替代数据
    /// </summary>
    public object Reserve
    {
        get { return (object)GetValue(ReserveProperty); }
        set { SetValue(ReserveProperty, value); }
    }
    public static readonly DependencyProperty ReserveProperty = DependencyProperty.Register("Reserve", typeof(object), typeof(BindingProxy), new PropertyMetadata(null));

    /// <summary>
    /// 阈值
    /// </summary>
    public double Thread
    {
        get { return (double)GetValue(ThreadProperty); }
        set { SetValue(ThreadProperty, value); }
    }
    public static readonly DependencyProperty ThreadProperty = DependencyProperty.Register("Thread", typeof(double), typeof(BindingProxy), new PropertyMetadata(0.0));
}

可直接调用资源词典

Converter.xaml

{Binding Converter={StaticResource Boolean2VisibilityConverter}}

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                    xmlns:converter="clr-namespace:XXX.Converters">
    <BooleanToVisibilityConverter x:Key="Boolean2VisibilityConverter"/>
    ......
</ResourceDictionary>

DataGrid中,编辑状态下触发事件

<DataGridTextColumn  Width="auto" IsReadOnly="False"  MinWidth="110"  Binding="{Binding Name}" Header="名称">
    <DataGridTextColumn.EditingElementStyle>
        <Style TargetType="TextBox">
            <EventSetter Event="TextChanged" Handler="DataGridTextColumn_Name_TextChanged"/>
            <EventSetter Event="LostFocus" Handler="DataGridTextColumn_Name_LostFocus"/>
        </Style>
    </DataGridTextColumn.EditingElementStyle>
</DataGridTextColumn>

RadioButton绑定属性

<UserControl.Resources>
    <cvt:RadioCheckConv x:Key="radioCheckConverter"/>
</UserControl.Resources>

<RadioButton Content="XXX" HorizontalAlignment="Center" GroupName="GroupName1" 
             IsChecked="{Binding PropertyName1, Converter={StaticResource radioCheckConverter}, ConverterParameter=1}"/>

其中,属性PropertyName1是可通知的;

using System;
using System.Windows.Data;
public class RadioCheckConv : IValueConverter
{
  public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
      if (value == null || parameter == null)
      {
          return false;
      }
      if (value.ToString().Equals(parameter.ToString()))
      {
          return true;
      }
      return false;
  }

  public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
  {
      if (value == null || parameter == null)
      {
          return null;
      }
      if ((bool)value)
      {
          return parameter.ToString();
      }
      return null;
  }
}

TextBox绑定属性

<TextBox x:name="txt" Text="{Binding PropertName, Mode=TwoWay, UpdateSourceTrigger=Default}" />

控件绑定属性时,UpdateSourceTrigger默认为Default。源PropertName不会随着Text属性的改变而立即更新;TextBox中的变化并不是立即传递到源,而是在TextBox失去焦点后,源才更新。

UpdateSourceTrigger枚举 说明 备注
Default 默认值 默认为LostFocuse
Explicit 当应用程序调用 UpdateSource 方法时生效 通过代码手动推送来更新
LostFocus 失去焦点的时候触发
PropertyChanged 属性改变的时候触发 源会立即更新
using System.Windows.Data;
private void btnUpdateSource_Click(object sender, RoutedEventArgs e)
{
    // Explicit时,手动更新绑定的属性
    BindingExpression binding = txt.GetBindingExpression(TextBox.TextProperty);
    binding.UpdateSource();
}

后台绑定

<cvt:IntToBoolConv x:Key="intToBoolConverter"/>
<CheckBox Content="启用" x:Name="CheckBox1"
   IsChecked="{Binding IsEnable, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged, Converter={StaticResource intToBoolConverter}}" />

this.DataContext = this;  // Prism可省略此步;此时IsEnable可通知客户端即可,不要求是依赖属性propdp

相当于后台实现

<CheckBox Content="启用" x:Name="CheckBox1"  />
using System.Windows.Data;
BindingOperations.SetBinding(CheckBox1,   // 控件名称
    CheckBox.IsCheckedProperty,           // 控件属性
    new Binding                           // 绑定内容
    {
        Path = new PropertyPath("IsEnable"), // 依赖属性 IsEnable
        Mode = BindingMode.TwoWay,
        UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged,
        Converter = new IntToBoolConv(),
        Source = this,                    // 属性所属对象
    });

原文地址:https://www.cnblogs.com/wesson2019-blog/p/12619655.html