[转载]WPF – 使用触发器
WPF提供了很重要的一個(gè)東西就是綁定Binding, 它幫助我們做了很多事情,這個(gè)我們?cè)?/span>WPF學(xué)習(xí)之綁定這篇里邊有講過(guò)。對(duì)于Binding我們可以設(shè)置其綁定對(duì)象,關(guān)系,并通過(guò)某種規(guī)則去驗(yàn)證輸入,或者轉(zhuǎn)換值等等,這一切的背后是省去了很多我們需要自己去處理的代碼。而對(duì)于WPF最主要表現(xiàn)的東西—渲染UI,當(dāng)然是我們必須去了解和把握的了。美工設(shè)計(jì)了很多效果,并把其設(shè)計(jì)成樣式展現(xiàn)(很大程度上我們應(yīng)該認(rèn)為Style也是一種資源),而作為程序員的我們不應(yīng)該只是簡(jiǎn)單的拿來(lái)這些拼湊的效果,根據(jù)程序的邏輯和用戶的操作來(lái)動(dòng)態(tài)的展現(xiàn)效果才是我們能發(fā)揮它對(duì)界面渲染的更好途徑。Trigger就給我們提供了很好的途徑去結(jié)合這些元素。
觸發(fā)器,從某種意義上來(lái)說(shuō)它也是一種Style,因?yàn)樗幸粋€(gè)Setter集合,并根據(jù)一個(gè)或多個(gè)條件執(zhí)行Setter中的屬性改變。因?yàn)閺?fù)用的緣故,Styles是放置觸發(fā)器的最好位置。但對(duì)于每個(gè)FrameworkElement來(lái)說(shuō)都有Triggers集合,你也可以放在Triggers集合里。觸發(fā)器有三種類型:
·???????? 屬性觸發(fā)器Property Trigger:當(dāng)Dependency Property的值發(fā)生改變時(shí)觸發(fā)。
·???????? 數(shù)據(jù)觸發(fā)器Data Trigger: 當(dāng)普通.NET屬性的值發(fā)生改變時(shí)觸發(fā)。
·???????? 事件觸發(fā)器Event Trigger: 當(dāng)路由時(shí)間被觸發(fā)時(shí)調(diào)用。
1.????? 屬性觸發(fā)器(Property Trigger)
屬性觸發(fā)器是WPF中最常用的觸發(fā)器類型,因?yàn)槲覀兦斑呎f(shuō)過(guò)依賴屬性具有垂直變更通知的功能,所以在使用屬性觸發(fā)器時(shí)會(huì)很方便,而且因?yàn)?/span>WPF中每個(gè)控件超過(guò)2/3的屬性都是依賴屬性,所以它用到的場(chǎng)合更多。屬性觸發(fā)器是在當(dāng)某個(gè)依賴屬性的值發(fā)生變化時(shí)觸發(fā)執(zhí)行一個(gè)Setter的集合,當(dāng)屬性失去這個(gè)值時(shí),這些被處罰執(zhí)行的Setter集合會(huì)自動(dòng)被撤銷。
例如,下邊的例子設(shè)置了當(dāng)鼠標(biāo)放置于按鈕之上懸停時(shí),按鈕的外表會(huì)發(fā)生變化。注意,屬性觸發(fā)器是用Trigger標(biāo)識(shí)的。
??????? <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ù)驗(yàn)證時(shí)用來(lái)顯示驗(yàn)證錯(cuò)誤信息。在WPF學(xué)習(xí)之綁定里的Validation部分我們附有用屬性觸發(fā)器來(lái)判斷是否有驗(yàn)證錯(cuò)誤并顯示相應(yīng)驗(yàn)證錯(cuò)誤信息的示例。
<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ā)器除了面對(duì)的對(duì)象類型不一樣外完全相同。數(shù)據(jù)觸發(fā)器是來(lái)檢測(cè)非依賴屬性------也就是用戶自定義的.NET屬性-----的值發(fā)生變化時(shí)來(lái)觸發(fā)并調(diào)用符合條件的一系列Setter集合。
下邊的示例演示了在綁定的ListBox里如果某個(gè)User對(duì)象符合某種特點(diǎn)(Role=Admin),則以突出方式顯示這個(gè)對(duì)象。這里就用了DataTrigger,因?yàn)槲覀冃枰獧z測(cè)的是User對(duì)象的屬性Role,這個(gè)對(duì)象是自定義的非可視化對(duì)象并且其屬性為普通.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中,其針對(duì)的是每個(gè)ListBox的項(xiàng),當(dāng)其被綁定的數(shù)據(jù)的屬性Role為Admin時(shí),突出顯示:
<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ā)器,顧名思義是在某個(gè)事件被觸發(fā)時(shí)來(lái)調(diào)用這個(gè)觸發(fā)器的相關(guān)操作。因?yàn)?/span>WPF提供了用XAML來(lái)標(biāo)記對(duì)象,事件等,所以其提供了一些在普通.NET開(kāi)發(fā)中看似沒(méi)用的屬性例如IsMouseOver, IsPressed等,這是為了XAML來(lái)用的,使其可以很方便的通過(guò)某個(gè)屬性來(lái)判斷狀態(tài),也方便了Property Trigger的應(yīng)用。而作為事件觸發(fā)器來(lái)說(shuō),它所做的事情和Property Trigger類似,不過(guò)是它的內(nèi)部不能是簡(jiǎn)單的Setter集合,而必須是TriggerAction的實(shí)例。
以下示例演示了如何應(yīng)用Event Trigger當(dāng)鼠標(biāo)點(diǎn)擊按鈕時(shí),讓按鈕的陰影效果發(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
截至目前我們討論的都是針對(duì)單個(gè)條件的觸發(fā)器,也就是說(shuō)當(dāng)某一個(gè)條件滿足時(shí)就會(huì)觸發(fā)。而現(xiàn)實(shí)中我們可能需要滿足很多個(gè)條件時(shí)才觸發(fā)一系列操作,這個(gè)時(shí)候就需要用到MultiDataTrigger或MultiTrigger。MutliDataTrigger和MultiTrigger都具有一個(gè)Conditions集合用來(lái)存放一些觸發(fā)條件,這里的Condition之間是and的關(guān)系,當(dāng)所有條件都滿足時(shí),Setter集合才會(huì)被調(diào)用。根據(jù)名字就可以看清楚:MultiDataTrigger用來(lái)實(shí)現(xiàn)多個(gè)數(shù)據(jù)觸發(fā)器(只用于普通.NET屬性)滿足條件時(shí)調(diào)用;MultiTrigger用來(lái)實(shí)現(xiàn)多個(gè)屬性觸發(fā)器(用于依賴屬性)滿足條件時(shí)調(diào)用。
以下示例僅當(dāng)按鈕的IsEenabled屬性為true,并且可見(jiàn)時(shí)(Visibility=Visible)會(huì)以醒目的方式顯示,否則當(dāng)IsEnabled屬性為false時(shí)將以灰色顯示。
<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"?? /> |
給按鈕添加單擊事件用來(lái)改變IsEnabled屬性:
private void?? Button_Click(object sender, RoutedEventArgs e) ????????? { ??????????? this.btnVisible.IsEnabled?? = !this.btnVisible.IsEnabled; ??????? } |
看看效果(左邊為不單擊后不滿足條件時(shí)的樣式):
同樣的,你也可以用MultiDataTrigger來(lái)對(duì)自定義的屬性進(jìn)行多條件的與關(guān)系操作。
5.????? 在觸發(fā)器中執(zhí)行用戶代碼
DependencyProperty.RegisterAttached方法允許用戶給控件/窗體等定義自己的依賴屬性,其包含的CallBack參數(shù)可以允許執(zhí)行某個(gè)特定方法。這允許我們?cè)?/span>Trigger中去調(diào)用特定的事件處理。其實(shí)嚴(yán)格的說(shuō)這和Trigger不太有關(guān)系,因?yàn)檫@相當(dāng)于我們給某個(gè)對(duì)象添加了自定義屬性并執(zhí)行某些事件。但trigger可以恰恰利用這個(gè)好處來(lái)簡(jiǎn)介的執(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 – 使用触发器的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 苹果欲借免费纳米SIM卡技术控制行业标准
- 下一篇: asp.net2.0中通过CS代码来动态