[转载]WPF – 使用触发器
WPF提供了很重要的一個東西就是綁定Binding, 它幫助我們做了很多事情,這個我們在WPF學(xué)習(xí)之綁定這篇里邊有講過。對于Binding我們可以設(shè)置其綁定對象,關(guān)系,并通過某種規(guī)則去驗證輸入,或者轉(zhuǎn)換值等等,這一切的背后是省去了很多我們需要自己去處理的代碼。而對于WPF最主要表現(xiàn)的東西—渲染UI,當(dāng)然是我們必須去了解和把握的了。美工設(shè)計了很多效果,并把其設(shè)計成樣式展現(xiàn)(很大程度上我們應(yīng)該認為Style也是一種資源),而作為程序員的我們不應(yīng)該只是簡單的拿來這些拼湊的效果,根據(jù)程序的邏輯和用戶的操作來動態(tài)的展現(xiàn)效果才是我們能發(fā)揮它對界面渲染的更好途徑。Trigger就給我們提供了很好的途徑去結(jié)合這些元素。
觸發(fā)器,從某種意義上來說它也是一種Style,因為它包含有一個Setter集合,并根據(jù)一個或多個條件執(zhí)行Setter中的屬性改變。因為復(fù)用的緣故,Styles是放置觸發(fā)器的最好位置。但對于每個FrameworkElement來說都有Triggers集合,你也可以放在Triggers集合里。觸發(fā)器有三種類型:
·???????? 屬性觸發(fā)器Property Trigger:當(dāng)Dependency Property的值發(fā)生改變時觸發(fā)。
·???????? 數(shù)據(jù)觸發(fā)器Data Trigger: 當(dāng)普通.NET屬性的值發(fā)生改變時觸發(fā)。
·???????? 事件觸發(fā)器Event Trigger: 當(dāng)路由時間被觸發(fā)時調(diào)用。
1.????? 屬性觸發(fā)器(Property Trigger)
屬性觸發(fā)器是WPF中最常用的觸發(fā)器類型,因為我們前邊說過依賴屬性具有垂直變更通知的功能,所以在使用屬性觸發(fā)器時會很方便,而且因為WPF中每個控件超過2/3的屬性都是依賴屬性,所以它用到的場合更多。屬性觸發(fā)器是在當(dāng)某個依賴屬性的值發(fā)生變化時觸發(fā)執(zhí)行一個Setter的集合,當(dāng)屬性失去這個值時,這些被處罰執(zhí)行的Setter集合會自動被撤銷。
例如,下邊的例子設(shè)置了當(dāng)鼠標放置于按鈕之上懸停時,按鈕的外表會發(fā)生變化。注意,屬性觸發(fā)器是用Trigger標識的。
??????? <Style x:Key="buttonMouseOver" TargetType="{x:Type Button}"> ??????????? <Style.Triggers> ??????????????? <Trigger Property="IsMouseOver" Value="True"> ??????????????????? <Setter Property="RenderTransform"> ??????????????????????? <Setter.Value> ??????????????????????????? <RotateTransform Angle="10"></RotateTransform> ??????????????????????? </Setter.Value> ??????????????????? </Setter> ??????????????????? <Setter Property="RenderTransformOrigin" Value="0.5,0.5"></Setter> ??????????????????? <Setter Property="Background" Value="#FF0CC030" /> ??????????????? </Trigger> ??????????? </Style.Triggers> ??????? </Style> |
屬性觸發(fā)器還經(jīng)常被用在做數(shù)據(jù)驗證時用來顯示驗證錯誤信息。在WPF學(xué)習(xí)之綁定里的Validation部分我們附有用屬性觸發(fā)器來判斷是否有驗證錯誤并顯示相應(yīng)驗證錯誤信息的示例。
<TextBox Style="{StaticResource validateTextBoxStyle}"> ??? <TextBox.Text> ??????? <Binding UpdateSourceTrigger="PropertyChanged" Path="Department"> ??????????? <Binding.ValidationRules> ??????????????? <local:JpgValidationRule/> ??????????? </Binding.ValidationRules> ??????? </Binding> ??? </TextBox.Text> </TextBox> …..
<Style x:Key="validateTextBoxStyle" TargetType="{x:Type TextBox}"> ??? <Setter Property="Width" Value="300" /> ??? <Style.Triggers> ??????? <Trigger Property="Validation.HasError" Value="True"> ??????????? <Setter Property="Background" Value="Red"/> ??????????????? <Setter Property="ToolTip" Value="{Binding RelativeSource={RelativeSource Self}, Path=(Validation.Errors)[0].ErrorContent}"/> ??????? </Trigger> ??? </Style.Triggers> </Style> |
2.????? 數(shù)據(jù)觸發(fā)器Data Trigger
數(shù)據(jù)觸發(fā)器和屬性觸發(fā)器除了面對的對象類型不一樣外完全相同。數(shù)據(jù)觸發(fā)器是來檢測非依賴屬性------也就是用戶自定義的.NET屬性-----的值發(fā)生變化時來觸發(fā)并調(diào)用符合條件的一系列Setter集合。
下邊的示例演示了在綁定的ListBox里如果某個User對象符合某種特點(Role=Admin),則以突出方式顯示這個對象。這里就用了DataTrigger,因為我們需要檢測的是User對象的屬性Role,這個對象是自定義的非可視化對象并且其屬性為普通.NET屬性。
<Page.Resources> ??? <clr:Users x:Key="myUsers" /> ??? <DataTemplate DataType="{x:Type clr:User}"> ??????? <TextBlock Text="{Binding Path=Name}"/> ??? </DataTemplate> ??? ... </Page.Resources> <StackPanel> ??? <ListBox Width="200" ???????? ItemsSource="{Binding Source={StaticResource myUsers}}" /> </StackPanel> |
主要的部分定義在了Style中,其針對的是每個ListBox的項,當(dāng)其被綁定的數(shù)據(jù)的屬性Role為Admin時,突出顯示:
<Style TargetType="{x:Type ListBoxItem}"> ??? <Style.Triggers> ??????? <DataTrigger Binding="{Binding Path=Role}" Value="Admin"> ??????????? <Setter Property="Foreground" Value="Red" /> ??????? </DataTrigger> ??? </Style.Triggers> </Style> |
3.????? 事件觸發(fā)器 Event Trigger
事件觸發(fā)器,顧名思義是在某個事件被觸發(fā)時來調(diào)用這個觸發(fā)器的相關(guān)操作。因為WPF提供了用XAML來標記對象,事件等,所以其提供了一些在普通.NET開發(fā)中看似沒用的屬性例如IsMouseOver, IsPressed等,這是為了XAML來用的,使其可以很方便的通過某個屬性來判斷狀態(tài),也方便了Property Trigger的應(yīng)用。而作為事件觸發(fā)器來說,它所做的事情和Property Trigger類似,不過是它的內(nèi)部不能是簡單的Setter集合,而必須是TriggerAction的實例。
以下示例演示了如何應(yīng)用Event Trigger當(dāng)鼠標點擊按鈕時,讓按鈕的陰影效果發(fā)生變化。
<Button Margin="15" Width="200" Name="myButton"> ??????????? Click Me to Animate Drop Shadow! ??????????? <Button.BitmapEffect>
??????????????? <!-- This BitmapEffect is?? targeted by the animation. --> ??????????????? <DropShadowBitmapEffect x:Name="myDropShadowBitmapEffect" Color="Black" ShadowDepth="0" /> ??????????? </Button.BitmapEffect> ??????????? <Button.Triggers> ??????????????? <EventTrigger RoutedEvent="Button.Click"> ??????????????????? <BeginStoryboard> ??????????????????????? <Storyboard>
??????????????????????????? <!-- Animate the movement?? of the button. --> ??????????????????????????? <ThicknessAnimation ????????????? Storyboard.TargetProperty="Margin"?? Duration="0:0:0.5" ????????????? From="50,50,50,50" To="0,0,50,50" AutoReverse="True"?? />
??????????????????????????? <!-- Animate shadow depth?? of the effect. --> ??????????????????????????? <DoubleAnimation ????????????? Storyboard.TargetName="myDropShadowBitmapEffect" ????????????? Storyboard.TargetProperty="ShadowDepth" ????????????? From="0" To="30" Duration="0:0:0.5" ????????????? AutoReverse="True"?? />
??????????????????????????? <!-- Animate shadow?? softness of the effect. As ?????????????????? the Button appears to get?? farther from the shadow, ?????????????????? the shadow gets softer.?? --> ??????????????????????????? <DoubleAnimation ????????????? Storyboard.TargetName="myDropShadowBitmapEffect" ????????????? Storyboard.TargetProperty="Softness" ????????????? From="0" To="1" Duration="0:0:0.5" ????????????? AutoReverse="True"?? /> ??????????????????????? </Storyboard> ??????????????????? </BeginStoryboard> ??????????????? </EventTrigger> ??????????? </Button.Triggers> ??????? </Button> |
4.????? MultiDataTrigger & MultiTrigger
截至目前我們討論的都是針對單個條件的觸發(fā)器,也就是說當(dāng)某一個條件滿足時就會觸發(fā)。而現(xiàn)實中我們可能需要滿足很多個條件時才觸發(fā)一系列操作,這個時候就需要用到MultiDataTrigger或MultiTrigger。MutliDataTrigger和MultiTrigger都具有一個Conditions集合用來存放一些觸發(fā)條件,這里的Condition之間是and的關(guān)系,當(dāng)所有條件都滿足時,Setter集合才會被調(diào)用。根據(jù)名字就可以看清楚:MultiDataTrigger用來實現(xiàn)多個數(shù)據(jù)觸發(fā)器(只用于普通.NET屬性)滿足條件時調(diào)用;MultiTrigger用來實現(xiàn)多個屬性觸發(fā)器(用于依賴屬性)滿足條件時調(diào)用。
以下示例僅當(dāng)按鈕的IsEenabled屬性為true,并且可見時(Visibility=Visible)會以醒目的方式顯示,否則當(dāng)IsEnabled屬性為false時將以灰色顯示。
<Style TargetType="{x:Type Button}" x:Key="highlightStyle"> ??? <Style.Triggers> ??? <Trigger Property="IsEnabled" Value="false"> ??????? <Setter Property="Background" Value="#EEEEEE" /> ??? </Trigger>
??? <MultiTrigger> ??????? <MultiTrigger.Conditions> ??????????? <Condition Property="Visibility " Value="Visible" /> ??????????? <Condition Property="IsEnabled" Value="true" /> ??????? </MultiTrigger.Conditions> ??????? <Setter Property="BorderBrush" Value="Red"/> ??????????? <Setter Property="FontSize" Value="14" /> ??????????? <Setter Property="FontWeight" Value="Bold" /> ??????????? <Setter Property="Foreground" Value="Red" /> ??????? </MultiTrigger> ??????? </Style.Triggers> </Style> … <Button Style="{StaticResource highlightStyle}" Content="Hight Value" x:Name="btnVisible" Click="Button_Click"?? /> |
給按鈕添加單擊事件用來改變IsEnabled屬性:
private void?? Button_Click(object sender, RoutedEventArgs e) ????????? { ??????????? this.btnVisible.IsEnabled?? = !this.btnVisible.IsEnabled; ??????? } |
看看效果(左邊為不單擊后不滿足條件時的樣式):
同樣的,你也可以用MultiDataTrigger來對自定義的屬性進行多條件的與關(guān)系操作。
5.????? 在觸發(fā)器中執(zhí)行用戶代碼
DependencyProperty.RegisterAttached方法允許用戶給控件/窗體等定義自己的依賴屬性,其包含的CallBack參數(shù)可以允許執(zhí)行某個特定方法。這允許我們在Trigger中去調(diào)用特定的事件處理。其實嚴格的說這和Trigger不太有關(guān)系,因為這相當(dāng)于我們給某個對象添加了自定義屬性并執(zhí)行某些事件。但trigger可以恰恰利用這個好處來簡介的執(zhí)行業(yè)務(wù)邏輯:
public static readonly DependencyProperty?? SomethingHappenedProperty = DependencyProperty.RegisterAttached("SomethingHappened", typeof(bool), typeof(Window1),?? new PropertyMetadata(false, new PropertyChangedCallback(SomethingHappened))); ????????? public bool?? GetSomethingHappened(DependencyObject d) ????????? { ??????????? return?? (bool)d.GetValue(SomethingHappenedProperty); ????????? } ????????? public void?? SetSomethingHappened(DependencyObject d, bool value) ????????? { ????????????? d.SetValue(SomethingHappenedProperty, value); ????????? } ????????? public staticvoid SomethingHappened(DependencyObject d, DependencyPropertyChangedEventArgs?? e) ????????? { ??????????? //do?? something here ??????? } |
轉(zhuǎn)載于:https://www.cnblogs.com/fx2008/archive/2012/03/29/2423621.html
總結(jié)
以上是生活随笔為你收集整理的[转载]WPF – 使用触发器的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 苹果欲借免费纳米SIM卡技术控制行业标准
- 下一篇: python中如何中止一个线程