Skip to content
分类目录:

DataBinding & Converter

Post date:
Author:
Number of comments: no comments

绑定到Enum

<Window x:Class="ArticleExample.BindEnumFull"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:sys="clr-namespace:System;assembly=mscorlib" 
        SizeToContent="WidthAndHeight"
        Title="Enum binding">
    <Window.Resources>
        <ObjectDataProvider x:Key="EnumDataSource"
                            ObjectType="{x:Type sys:Enum}"
                            MethodName="GetValues">
            <ObjectDataProvider.MethodParameters>
                <x:Type TypeName="HorizontalAlignment" />
            </ObjectDataProvider.MethodParameters>
        </ObjectDataProvider>
    </Window.Resources>
    
    <StackPanel Width="300" Margin="10">
        <TextBlock>Choose the HorizontalAlignment value of the Button:</TextBlock>

        <ListBox Name="myComboBox" SelectedIndex="0"
                 ItemsSource="{Binding Source={StaticResource EnumDataSource}}"/>

        <Button Content="I'm a button"
                HorizontalAlignment="{Binding ElementName=myComboBox, Path=SelectedItem}" />
    </StackPanel>
</Window>

Binding :

BindingBase => Binding and MultiBinding

常见的Binding方式:

1. ElementName绑定到UI的另外一个元素上,并指定Path

<Window>
  <StackPanel>
	<Slider Name="sliderFontSize" 
    Minimum="1" Maximum="40" Value="10" 
    TickFrequency="1" TickPlacement="TopLeft"/>

    <TextBlock Text="SimpleText" 
      FontSize="{Binding ElementName=sliderFontSize, Path=Value}"/>
  </StackPanel>  
</Window>
//binding sample with code
Binding binding = new Binding();
binding.Source=sliderObj;
binding.Path= new PropertyPath("Value");
binding.Mode=BindingMode.TwoWay;
tbObj.SetBinding(TextBlock.FontSize,binding);

//查询绑定
Binding binding = BindingOperations.GetBindinig(tbObj,TextBlock.FontSize);

2. 通过Source指定绑定源

使用Source可以绑定到静态类的属性上,或者Resource中的资源

绑定到数据本身,如int或者string等基本类型时,Path可以省略,或者以 . 表示。

<TextBlock Text="{Binding Source={x:Static SystemFonts.IconFontFammily,Path=Source}}"/>

<!--Or -->
<Window.Resources>
	<FontFamily x:Key="CustomFont">Calibri</FontFamily>
</Window.Resources>

<TextBlock Text="{Binding Source={StaticResource CustomFont,Path=Source}}" />

3. 通过RelativeSource指定绑定源

RelativeSource主要包括:

Self: 表达式绑定到同一元素的另一个属性上

FindAncestor: 表达式绑定到父元素

PreviousData: 表达式绑定到数据绑定列表中的前一个数据项

TemplateParent: 表达式绑定到应用模板的元素,只有当绑定位于控件控件模板或数据模板内部时,这种模式才能工作。

<TextBlock Text="{Binding Path=Title,
  RelativeSource={RelativeSource FindAncestor,AncestorType={x:Type Window}} }"/>

<!-- FindAncestor模式-->
Self,FindAncestor,PreviousData,TemplatedParent

<ControlTemplate TargetType="ListBoxItem">
  <RadioButton 
    IsChecked=”{Binding 
    Path=IsSelected,
    RelativeSource={RelativeSource TemplatedParent},
    Mode=TwoWay}”>
    <ContentPresenter></ContentPresenter>
</ControlTemplate>

<!--还可以绑定到附加属性 -->
<Condition 
  Binding="{Binding Path=(local:TextBoxHelper.FocusedBorderBrush)
  ,RelativeSource={RelativeSource Self}
  , Mode=OneWay
  ,Converter={StaticResource IsNotNullConverter}}"
  Value="True" />

4. 通过DataContext指定绑定源

此种方式无需指定Source,通过DataContext绑定,控件会沿着控件树向上依次查找本身或者父元素的DataContext。

在xaml文件中配置d:DataContext,可以在VS的设计模式,输入绑定时,提示ViewModel的信息,并且也可以F12导航到对应的代码。

xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
d:DataContext="{d:DesignInstance local:MainWindowViewModel}"

<TextBox Text="{Binding Name}"/>

当Binding中写了. 符号后,绑定的对象试剂上是DataContext指向的对象,即ViewModel

如果是在ItemsControl中使用{Binding},则指向的是该行对应的集合里的单个Model

如:

<UserControl DataContext="{Binding VM}"> 
  <Button Command="{Binding TestCommand}" CommandParameter="{Binding .}">Test</Button>
</UserControl>

public class UserControlViewMiodel :BindableBase{

	public DelegateCommand<object> TestCommand{get;private set;} 
                 = new DelegateCommand<object>(TestCmdHandler);

    private void TestCmdHandler(object obj)
    {
      	//obj为Button对应的DataContext,如没设置,则找Button的父节点的DataContext
    }

}

绑定模式(Mode):

BindingMode主要包括以下几种:

OneWay:单向绑定,当数据源变化时,更新目标属性

TwoWay:双向绑定,主要是一些表单控件,当源属性变化时,更新目标属性,并且当目标属性变化时更新数据源

OneTime:只有第一次的绑定会生效

OneWayToSource:单向绑定,与OneWay相反

Default:大多数的行为是OneWay,但TextBox.Text是双向的。

绑定更新:

PropertyChanged:当控件属性变化时,更新数据源

LostFocus:当控件属性发生变化且丢失焦点时,更新数据源

Explicit:除非调用BindingExpression.UpdateSource(),否则无法更新数据源

Default: 大多数的默认行为时PropertyChanged,但TextBox.Text的默认行为是LostFocus

绑定Model

如果是集合类型,则使用ObservableCollection<T>类型来实现集合绑定,才具有通知的功能。

如果要绑定到集合的某个项,则

<Button DataContext="{Binding CellList[0]}"/>

MultiBinding:

<Button.CommandParameter>
    <MultiBinding Converter="{StaticResource MultiCombinerConverter}">
        <Binding Path="."
    RelativeSource="{RelativeSource AncestorType=TabItem}" />
    <Binding Path="."
    RelativeSource="{RelativeSource AncestorType=TabControl}" />
    </MultiBinding>
</Button.CommandParameter>

<TextBlock Text="{Binding KeyValue}">
    <TextBlock.Foreground>
        <MultiBinding Converter="{StaticResource boolBrushValueConverter}">
            <Binding Path="KeyName"/>
            <Binding Path="KeyValue"/>
            <Binding Path="KeyReferValue"/>
        </MultiBinding>
    </TextBlock.Foreground>
</TextBlock>

<TextBlock.Text>
    <MultiBinding StringFormat="{}{0} / {1}{5} / {2}({3}{4})">
        <Binding Path="Sex" Converter="{StaticResource SexConverter}"/>
        <Binding Path="PatientWeight"/>
        <Binding Path="Birthdate" Converter="{StaticResource BirthDateConverter}"/>
        <Binding Path="Age" />
    <Binding Path="AgeType" Converter="{StaticResource AgeTypeConverter}" />                                    
    <Binding Source="{StaticResource kg}"/>                                    
    </MultiBinding>
</TextBlock.Text>

参考 WPF 编程宝典第 4 版:第 20 章

String.Format 的使用:

IvalueConverter 的使用:

1.新建类实现 IvalueConverter 接口

2.在 xaml 文件中引入 xmlns 对应的程序集和命名空间

3.在 xaml 文件的 Resource 中定义此 key

4.在 xaml 文件绑定的元素出使用此 converter

如:

namespace System.Windows.Data;
public interface IValueConverter
{
    //从Data到UI
    object Convert(object value, Type targetType, object parameter, CultureInfo culture);
    //从UI到Data
    object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture);
}

Xaml 文件中的更改:

xmlns:local="clr-namespace:NMS.MR.FieldService.UI.GradientAmplifierStatus"

<UserControl.Resources>
  <local:StatusValueConverter x:Key="StatusValueConverter"/>
</UserControl.Resources>
//此处的parameter为string类型
<Rectangle Width="10" Height="10" 
  Fill="{Binding Path=StatusValue,
  Converter={StaticResource StatusValueConverter},
  ConverterParameter=1}"/>

IMultiValueConverter:

参考 WPF 编程宝典第 4 版:20.2.6

1.定义 Convert

public class BoolBrushValueConverter : IMultiValueConverter
{
    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values.Length != 3) return Brushes.White;
        String keyName = values[0].ToString();
        String keyValue = values[1].ToString();
        String referValue = values[2].ToString();
        return Brushes.Red;
    }
}

2.在 XAML 文件中定义 Convert 资源

<UserControl.Resources>
<diagnosis:BoolBrushValueConverter x:Key="boolBrushValueConverter"/>
</UserControl.Resources>

3.MultiBinding 的使用

<DataGrid IsReadOnly="True" ItemsSource="{Binding DspInfo_1}" Margin="10,10"
    ColumnHeaderStyle="{StaticResource Header}" RowStyle="{StaticResource RowStyle}"
    HorizontalAlignment="Stretch" VerticalAlignment="Stretch" AutoGenerateColumns="False" Style="{DynamicResource Style}">
    <DataGrid.Columns>
        <DataGridTextColumn Width="*" Header="Name" Binding="{Binding KeyName }" CellStyle="{StaticResource DataGridCell}" />
    <DataGridTemplateColumn Width="*" Header="Value">
            <DataGridTemplateColumn.CellTemplate>
                <DataTemplate>
                    <TextBlock Text="{Binding KeyValue}">
                        <TextBlock.Foreground>
                            <MultiBinding Converter="{StaticResource boolBrushValueConverter}">
                                <Binding Path="KeyName"/>
                                <Binding Path="KeyValue"/>
                                <Binding Path="KeyReferValue"/>
                            </MultiBinding>
                        </TextBlock.Foreground>
                    </TextBlock>
                </DataTemplate>
            </DataGridTemplateColumn.CellTemplate>
        </DataGridTemplateColumn>
        <DataGridTextColumn Width="*" Header="ReferValue" Binding="{Binding KeyReferValue,Mode=TwoWay}" CellStyle="{StaticResource DataGridCell}" />
    </DataGrid.Columns>
</DataGrid>

或者结合 RelativeSource

<TextBlock.Visibility>
     <MultiBinding Converter="{StaticResource SnVisibConverter}">
         <Binding Path="IsSelected" RelativeSource="{RelativeSource AncestorType=ListBoxItem}" />
    <Binding Path="IsMouseOver" RelativeSource="{RelativeSource AncestorType=ListBoxItem}" />
    </MultiBinding>
</TextBlock.Visibility>

发表回复

您的电子邮箱地址不会被公开。 必填项已用 * 标注

豫ICP备2021008859号-1