Binding

binding之基本概念

binding之數據源和目標控件

binding 之 Data Convert

DataSource的Property和TargetControl的DependencyProperty綁定,若是兩個Property的數據類型不一樣,則須要轉換。this

bind.Convert = new DataConverter():IValueConverter
Convert屬性的類型是IValueConverter
public interface IValueConverter
    {
        object Convert(object value, Type outType, object parameter, CultureInfo culture);
        object ConvertBack(object value, Type outType, object parameter, CultureInfo culture);
    }

Convert用於將數據源屬性轉換成目標控件屬性。spa

value:數據源屬性值
outType:轉換後的數據類型
parameter:額外參數

ConvertBack用於將目標控件屬性轉換成數據源屬性。code

示例

後臺數據源的SexCode,0表示女,1表示男,綁定到TextBlock。blog

class Sex
{
    public int SexCode { get; set; }
}
Sex sex = new Sex();
Binding bind = new Binding();
bind.Source = sex;
bind.Path = new PropertyPath("SexCode");
bind.Converter = new DataConvert();
BindingOperations.SetBinding(tbkSex, TextBlock.TextProperty, bind);
class DataConvert : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        int sexCode = (int)value;
        if(sexCode == 0)
        {
            return "女";
        }
        else
        {
            return "男";
        }
    }

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

示例

使用Binding的ConverterParameter的參數,使DataConvert複用,能被多個binding實例使用。繼承

class Sex
{
    public int SexCode { get; set; }
}

class DataConvert : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        bool usage = (bool)parameter;
        if (usage)
        {
            int sexCode = (int)value;
            if (sexCode == 0)
            {
                return "女";
            }
            else if (sexCode == 1)
            {
                return "男";
            }
            else
            {
                return "保密";
            }
        }
        else
        {
            int isCoder = (int)value;
            if(isCoder == 0)
            {
                return false;
            }
            else if(isCoder == 1)
            {
                return true;
            }
            else
            {
                return null;
            }
        }
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
Sex sex = new Sex { SexCode = 3};
Binding bind = new Binding();
bind.Source = sex;
bind.Path = new PropertyPath("SexCode");
bind.Converter = new DataConvert();
bind.ConverterParameter = true;
BindingOperations.SetBinding(tbkSex, TextBlock.TextProperty, bind);
bind = new Binding();
bind.Source = sex;
bind.Path = new PropertyPath("SexCode");
bind.Converter = new DataConvert();
bind.ConverterParameter = false;
cbxIsCoder.SetBinding(System.Windows.Controls.Primitives.ToggleButton.IsCheckedProperty, bind);

image.png

Binding之Data Invalidation

校驗是指改變目標控件的屬性,會校驗屬性的新值,合理則更新數據源,不合理則改變控件的樣式進行報錯,且不更新數據源。
Binding能夠有多個校驗規則,一條校驗規則是一個繼承自抽象類的ValidationRule的類實例。Binding的屬性ValidationRules,類型是Collection<ValidationRule>。繼承抽象類ValidationRule實現其Validation方法,返回類型是ValidationResult,校驗失敗,則ValidationResult.IsValid = false;ValidationResult.ErrorContent = "錯誤信息";校驗成功爲true和null。事件

public abstract class ValidationRule
{
    protected ValidationRule(ValidationStep validationStep, bool validatesOnTargetUpdated);
    public abstract ValidationResult Validate(object value, CultureInfo cultureInfo);
}
public class ValidationResult
{
    public ValidationResult(bool isValid, object errorContent);
    public static ValidationResult ValidResult { get; }
    public object ErrorContent { get; }
    public bool IsValid { get; }
}
<TextBox Width="150"
         Validation.Error="ItemError">
  <TextBox.Text>
    <Binding Source="{StaticResource myObject}"
             Path="PropertyB"
             UpdateSourceTrigger="PropertyChanged"
             NotifyOnValidationError="True">
      <Binding.ValidationRules>
        <src:ValueIsNotNull ValidatesOnTargetUpdated="True" />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

校驗失敗,咱們須要改變控件樣式,來警告或提醒用戶,與該狀況相關的類是Invalidation。
控件有個Errors屬性,類型是Collection<ValidationError>,每一個校驗規則的返回值的ValidationResult的ErrorContent會填充到該集合。
Invalidation.GetErrors(目標控件)[0].ErrorContent.ToString()能拿到第一條檢驗失敗的錯誤信息。ip

三種提醒方式

  1. 發生錯誤時,Binding會觸發Valiation.ErrorEvent路由事件,沿着目標控件在UI樹上向上傳播,咱們對目標控件或者UI樹位置高於目標控件的控件增添路由事件,在路由事件裏面,更改控件的外觀屬性,ToolTip,彈窗等,來提醒出錯。

this.AddHandler(Validation.Error,new RoutedEventHandler(this.ErrorHandler));
或者經過XAML設置 Validation.Error = "ErrorHandler"
2.
ToolTip = "{Binding RelativeSource = {RelativeSource self},Path=(Validation.Errors)[0].ErrorContent.ToString}"
3.設置ErrorTemplate。
image.png路由

<Grid>
    <StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
        <TextBox x:Name="textText" MinHeight="70" MinWidth="200" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" Validation.Error="textText_Error">
            <TextBox.Resources>
                <local:Student Age="24" x:Key="dataSource"/>
            </TextBox.Resources>
            <TextBox.Text>
                <Binding Source="{StaticResource dataSource}" Path="Age" Mode="TwoWay" NotifyOnValidationError="True" UpdateSourceTrigger="PropertyChanged">
                    <Binding.ValidationRules>
                        <local:DataInvalidation ValidatesOnTargetUpdated="True"/>
                    </Binding.ValidationRules>
                </Binding>
            </TextBox.Text>
        </TextBox>
    </StackPanel>
</Grid>

多路綁定

相關文章
相關標籤/搜索