日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > asp.net >内容正文

asp.net

WPF入门教程系列十四——依赖属性(四)

發(fā)布時間:2025/3/15 asp.net 20 豆豆
生活随笔 收集整理的這篇文章主要介紹了 WPF入门教程系列十四——依赖属性(四) 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

六、依賴屬性回調(diào)、驗證及強(qiáng)制值

??? 我們通過下面的這幅圖,簡單介紹一下WPF屬性系統(tǒng)對依賴屬性操作的基本步驟:

?

  借用一個常見的圖例,介紹一下WPF屬性系統(tǒng)對依賴屬性操作的基本步驟:?

  • 第一步,確定Base Value,對同一個屬性的賦值可能發(fā)生在很多地方。比如控件的背景(Background),可能在Style或者控件的構(gòu)造函數(shù)中都對它進(jìn)行了賦值,這個Base Value就要確定這些值中優(yōu)先級最高的值,把它作為Base Value。
  • 第二步,估值。如果依賴屬性值是計算表達(dá)式(Expression),比如說一個綁定,WPF屬性系統(tǒng)就會計算表達(dá)式,把結(jié)果轉(zhuǎn)化成一個實際值。
  • 第三步,動畫。動畫是一種優(yōu)先級很高的特殊行為。如果當(dāng)前屬性正在作動畫,那么因動畫而產(chǎn)生的值會優(yōu)于前面獲得的值,這個也就是WPF中常說的動畫優(yōu)先。
  • 第四步,強(qiáng)制。如果我們在FrameworkPropertyMetadata中傳入了 CoerceValueCallback委托,WPF屬性系統(tǒng)會回調(diào)我們傳入的的delagate,進(jìn)行屬性值的驗證,驗證屬性值是否在我們允許的范圍之內(nèi)。例如強(qiáng)制設(shè)置該值必須大于于0小于10等等。在屬性賦值過程中,Coerce擁有 最高的優(yōu)先級,這個優(yōu)先級要大于動畫的優(yōu)先級別。
  • 第五步,驗證。驗證是指我們注冊依賴屬性如果提供了ValidateValueCallback委托,那么最后WPF會調(diào)用我們傳入的delegate,來驗證數(shù)據(jù)的有效性。當(dāng)數(shù)據(jù)無效時會拋出異常來通知。

  那么應(yīng)該如何使用這些功能呢?

前面我們講了基本的流程,下面我們就用一個小的例子來進(jìn)行說明:

XAML的代碼如下:

?

<Window x:Class="WpfApp1.WindowValid"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"Title=" WindowValid " Height="300" Width="400"><Grid><StackPanel> <Button Name="btnDPTest" Click="btnDPTest_Click" >屬性值執(zhí)行順序測試</Button></StackPanel></Grid></Window>

?

C#的代碼如下:

?

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading;using System.Threading.Tasks;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Shapes;using System.Windows.Threading;using WpfApp1.Models;namespace WpfApp1{/// <summary>/// WindowThd.xaml 的交互邏輯/// </summary>public partial class WindowValid: Window{public WindowValid (){InitializeComponent();}private void btnDPTest_Click(object sender, RoutedEventArgs e){SimpleDP test = new SimpleDP();test.ValidDP = 1;} }}using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows;namespace WpfApp1.Models{public class SimpleDP : DependencyObject{public static readonly DependencyProperty ValidDPProperty =DependencyProperty.Register("ValidDP", typeof(int), typeof(SimpleDP),new FrameworkPropertyMetadata(0,FrameworkPropertyMetadataOptions.None,new PropertyChangedCallback(OnValueChanged),new CoerceValueCallback(CoerceValue)),new ValidateValueCallback(IsValidValue));public int ValidDP{get { return (int)GetValue(ValidDPProperty); }set { SetValue(ValidDPProperty, value); }}private static void OnValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){Console.WriteLine("當(dāng)屬性值的OnValueChanged方法被調(diào)用,屬性值為: {0}", e.NewValue);}private static object CoerceValue(DependencyObject d, object value){Console.WriteLine("當(dāng)屬性值的CoerceValue方法被調(diào)用,屬性值強(qiáng)制為: {0}", value);return value;}private static bool IsValidValue(object value){Console.WriteLine("當(dāng)屬性值的IsValidValue方法被調(diào)用,對屬性值進(jìn)行驗證,返回bool值,如果返回True表示嚴(yán)重通過,否則會以異常的形式拋出: {0}", value);return true;} }}

?

結(jié)果如下:

?

  當(dāng)ValidDP屬性變化之后,PropertyChangeCallback就會被調(diào)用。可以看到結(jié)果并沒有完全按照我們先前的流程先 Coerce后Validate的順序執(zhí)行,有可能是WPF內(nèi)部做了什么特殊處理,當(dāng)屬性被修改時,首先會調(diào)用Validate來判斷傳入的value是 否有效,如果無效就不繼續(xù)后續(xù)的操作,這樣可以更好的優(yōu)化性能。從上面的結(jié)果上看出,CoerceValue后面并沒有立即ValidateValue, 而是直接調(diào)用了PropertyChanged。這是因為前面已經(jīng)驗證過了value,如果在Coerce中沒有改變value,那么就不用再驗證了。如 果在 Coerce中改變了value,那么這里還會再次調(diào)用ValidateValue操作,和前面的流程圖執(zhí)行的順序一樣,在最后我們會調(diào)用 ValidateValue來進(jìn)行最后的驗證,這就保證最后的結(jié)果是我們希望的那樣了。

  上面簡單介紹了處理流程,下面我們就以一個案例來具體看一看上面的流程到底有沒有出入。

?

依賴屬性代碼文件如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows;namespace WpfApp1.Controls{class MyValiDP:System.Windows.Controls.Control{ //注冊Current依賴屬性,并添加PropertyChanged、CoerceValue、ValidateValue的回調(diào)委托public static readonly DependencyProperty CurrentValueProperty = DependencyProperty.Register("CurrentValue",typeof(double),typeof(MyValiDP),new FrameworkPropertyMetadata(Double.NaN,FrameworkPropertyMetadataOptions.None,new PropertyChangedCallback(OnCurrentValueChanged),new CoerceValueCallback(CoerceCurrentValue)),new ValidateValueCallback(IsValidValue));//屬性包裝器,通過它來暴露Current的值public double CurrentValue{get { return (double)GetValue(CurrentValueProperty); }set { SetValue(CurrentValueProperty, value); }}//注冊Min依賴屬性,并添加PropertyChanged、CoerceValue、ValidateValue的回調(diào)委托public static readonly DependencyProperty MinValueProperty = DependencyProperty.Register("MinValue",typeof(double),typeof(MyValiDP),new FrameworkPropertyMetadata(double.NaN,FrameworkPropertyMetadataOptions.None,new PropertyChangedCallback(OnMinValueChanged),new CoerceValueCallback(CoerceMinValue)),new ValidateValueCallback(IsValidValue));//屬性包裝器,通過它來暴露Min的值public double MinValue{get { return (double)GetValue(MinValueProperty); }set { SetValue(MinValueProperty, value); }}//注冊Max依賴屬性,并添加PropertyChanged、CoerceValue、ValidateValue的回調(diào)委托public static readonly DependencyProperty MaxValueProperty = DependencyProperty.Register("MaxValue",typeof(double),typeof(MyValiDP),new FrameworkPropertyMetadata(double.NaN,FrameworkPropertyMetadataOptions.None,new PropertyChangedCallback(OnMaxValueChanged),new CoerceValueCallback(CoerceMaxValue)),new ValidateValueCallback(IsValidValue));//屬性包裝器,通過它來暴露Max的值public double MaxValue{get { return (double)GetValue(MaxValueProperty); }set { SetValue(MaxValueProperty, value); }}//在CoerceCurrent加入強(qiáng)制判斷賦值private static object CoerceCurrentValue(DependencyObject d, object value){MyValiDP g = (MyValiDP)d;double current = (double)value;if (current < g.MinValue) current = g.MinValue;if (current > g.MaxValue) current = g.MaxValue;return current;}//當(dāng)Current值改變的時候,調(diào)用Min和Max的CoerceValue回調(diào)委托private static void OnCurrentValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){d.CoerceValue(MinValueProperty);d.CoerceValue(MaxValueProperty);}//當(dāng)OnMin值改變的時候,調(diào)用Current和Max的CoerceValue回調(diào)委托private static void OnMinValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){d.CoerceValue(MaxValueProperty);d.CoerceValue(CurrentValueProperty);}//在CoerceMin加入強(qiáng)制判斷賦值private static object CoerceMinValue(DependencyObject d, object value){MyValiDP g = (MyValiDP)d;double min = (double)value;if (min > g.MaxValue) min = g.MaxValue;return min;}//在CoerceMax加入強(qiáng)制判斷賦值private static object CoerceMaxValue(DependencyObject d, object value){MyValiDP g = (MyValiDP)d;double max = (double)value;if (max < g.MinValue) max = g.MinValue;return max;}//當(dāng)Max值改變的時候,調(diào)用Min和Current的CoerceValue回調(diào)委托private static void OnMaxValueChanged(DependencyObject d, DependencyPropertyChangedEventArgs e){d.CoerceValue(MinValueProperty);d.CoerceValue(CurrentValueProperty);}//驗證value是否有效,如果返回True表示驗證通過,否則會提示異常public static bool IsValidValue(object value){Double v = (Double)value;return (!v.Equals(Double.NegativeInfinity) && !v.Equals(Double.PositiveInfinity));}}}

?

?

XAML代碼如下:

<Window x:Class="WpfApp1.WindowProcess"xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"xmlns:local="clr-namespace:WpfApp1.Controls"Title="WindowProcess" Height="400" Width="500"><Grid><StackPanel Orientation="Vertical"><local:MyValiDP x:Name="myValiDP1" MaxValue="500" MinValue="0" /><Label Content="可以設(shè)置最小值為0和最小大值為500" Height="30"/><StackPanel Orientation="Horizontal" Height="60"><Label Content="當(dāng)前值為 : "/><Label Background="Yellow" BorderBrush="Black" BorderThickness="1"IsEnabled="False" Content="{Binding ElementName=myValiDP1, Path=CurrentValue}" Height="25" VerticalAlignment="Top" /></StackPanel><WrapPanel ><Label Content="最小值" /><Slider x:Name="sliderMin" Minimum="-200" Maximum="100" Width="300" ValueChanged="sliderMin_ValueChanged" SmallChange="10" /><Label Content="{Binding ElementName=sliderMin, Path=Value}" /></WrapPanel><WrapPanel ><Label Content="最大值" /><Slider x:Name="sliderMax" Minimum="200" Maximum="800" Width="300" ValueChanged="sliderMax_ValueChanged" SmallChange="10" /><Label Content="{Binding ElementName=sliderMax, Path=Value}" /></WrapPanel></StackPanel></Grid></Window>

?

?

C#代碼如下:

using System;using System.Collections.Generic;using System.Linq;using System.Text;using System.Threading.Tasks;using System.Windows;using System.Windows.Controls;using System.Windows.Data;using System.Windows.Documents;using System.Windows.Input;using System.Windows.Media;using System.Windows.Media.Imaging;using System.Windows.Shapes; namespace WpfApp1 {/// <summary>/// WindowProcess.xaml 的交互邏輯/// </summary>public partial class WindowProcess : Window{public WindowProcess(){InitializeComponent();//設(shè)置Current的值myValiDP1.CurrentValue = 100;}private void sliderMin_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e){//設(shè)置Current的值myValiDP1.CurrentValue = (int)sliderMin.Value;}private void sliderMax_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e){//設(shè)置Current的值myValiDP1.CurrentValue = (int)sliderMax.Value;}}}

示例效果如下圖。

  在上面的例子中,一共有三個依賴屬性相互作用——CurrentValue、MinValue和MaxValue,這些屬性相互作 用,但它們的規(guī)則是MinValue≤CurrentValue≤MaxValue。根據(jù)這個規(guī)則,當(dāng)其中一個依賴屬性變化時,另外兩個依賴 屬性必須進(jìn)行適當(dāng)?shù)恼{(diào)整,這里我們要用到的就是CoerceValue這個回調(diào)委托,那么實現(xiàn)起來也非常的簡單,注冊MaxValue的時候加入 CoerceValueCallback,在CoerceMaxValue函數(shù)中做處理:如果Maximum的值小于MinValue,則使 MaxValue值等于MinValue;同理在CurrentValue中也加入了CoerceValueCallback進(jìn)行相應(yīng)的強(qiáng)制 處理。然后在MinValue的ChangedValueCallback被調(diào)用的時候,調(diào)用CurrentValue和MaxValue的 CoerceValue回調(diào)委托,這樣就可以達(dá)到相互作用的依賴屬性一變應(yīng)萬變的”千機(jī)變“。

???? 換句話說,當(dāng)相互作用的幾個依賴屬性其中一個發(fā)生變化時,在它的PropertyChangeCallback中調(diào)用受它影響的依賴屬性的CoerceValue,這樣才能保證相互作用關(guān)系的正確性。 前面也提高ValidateValue主要是驗證該數(shù)據(jù)的有效性,最設(shè)置了值以后都會調(diào)用它來進(jìn)行驗證,如果驗證不成功,則拋出異常。

?

轉(zhuǎn)載于:https://www.cnblogs.com/chillsrc/p/4688983.html

總結(jié)

以上是生活随笔為你收集整理的WPF入门教程系列十四——依赖属性(四)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。