WPF 基礎 - Binding 對數據的轉換和校驗

1. Binding 對數據的轉換和校驗

Binding 中,有檢驗和轉換關卡。ide

1.1 數據校驗

源碼:this

namespace System.Windows.Data
{
    public class Binding : BindingBase
    {
        ...
        public Collection<ValidationRule> ValidationRules { get; }    
        ...
    }
}

namespace System.Windows.Controls
{
    //
    // 摘要:
    //     提供建立自定義規則的一個方式,旨在檢查用戶輸入的有效性。
    public abstract class ValidationRule
    {
        public abstract ValidationResult Validate(object value, CultureInfo cultureInfo);
    }
    
    //
    // 摘要:
    //     表示 ValidationRule.Validate(Object, CultureInfo)方法返回的結果。
    public class ValidationResult
    {
        public bool IsValid { get; }
        public object ErrorContent { get; }
    }
}

實例:spa

<Slider x:Name="sliderA" Minimum="0" Maximum="100"/>
<TextBox x:Name="textBoxA"/>
        
public class RangeValidationRule : ValidationRule
{
    public override ValidationResult Validate(object value, CultureInfo cultureInfo)
    {
        double d = 0;
        if (double.TryParse(value.ToString(), out d))
        {
            if (d >= 0 && d <= 10)
            {
                return new ValidationResult(true, null);
            }
        }

        return new ValidationResult(false, "Validation Failed");
    }
}

RangeValidationRule rvr = new RangeValidationRule();

Binding bindingS = new Binding("Value") { Source = this.sliderA };
bindingS.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
bindingS.ValidationRules.Add(rvr);

this.textBoxA.SetBinding(TextBox.TextProperty, bindingS);

拓展:

  1. RangeValidationRule 默認只檢驗從 Target 回 Source 的數據傳遞,默認從 Source 傳過來的數據是合法的,若是想校驗從 Source 傳過來的數據,需設置 rvr.ValidatesOnTargetUpdated = true;
  2. 若是想監聽校驗失敗的事件,設置 bindingS.NotifyOnValidationError = true,併爲路由事件指定處理程序。

源碼:code

namespace System.Windows.Controls
{
    public static class Validation
    {
        // 校驗失敗時觸發的事件
        public static readonly RoutedEvent ErrorEvent;
    }
    
    //
    // 摘要:
    //     表示一個驗證錯誤,該錯誤可經過 System.Windows.Controls.ValidationRule 報告驗證錯誤時由綁定引擎建立
    public class ValidationError
    {
        public object ErrorContent { get; set; }
    }
}

實例:事件

RangeValidationRule rvr = new RangeValidationRule();
rvr.ValidatesOnTargetUpdated = true;

bindingS.ValidationRules.Add(rvr);
bindingS.NotifyOnValidationError = true;

this.textBoxA.SetBinding(TextBox.TextProperty, bindingS);       
this.textBoxA.AddHandler(Validation.ErrorEvent, new RoutedEventHandler(this.ValidationError));

private void ValidationError(object sender, RoutedEventArgs e)
{
    if (Validation.GetErrors(this.textBoxA).Count > 0)
    {
        MessageBox.Show(Validation.GetErrors(this.textBoxA)[0].ErrorContent.ToString();
    }
}

1.2 數據轉換

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

public enum Category 
{
    Bomber,
    Fighter
}
public class CategoryToSourceConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        Category c = (Category)value; 
        switch (c)
        {
            case Category.Bomber:
                return @"llcons\Bomber.png"; 
            case Category.Fighter: 
                return @"\lcoos\Fighter.png";
            default: 
                return null;
        }
    }

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

<Window.Resources>
    <local:CategoryToSourceConverter x:Key="cts"/>
</Window.Resources>

<Image Widlh="20" Height="20"
       Source="{Binding Path=Category, Converter={StaticResoun cts}}"/>
相關文章
相關標籤/搜索