您好,登錄后才能下訂單哦!
這篇文章給大家介紹System.Windows.Interactivity怎么在c# 項目中使用,內容非常詳細,感興趣的小伙伴們可以參考借鑒,希望對大家能有所幫助。
通過在代碼中引入System.Windows.Interactivity.dll,引入了這個dll后我們就能夠使用這個里面的方法來將事件映射到ViewModel層了,我們來看看具體的使用步驟,第一步就是引入命名控件
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"
另外還可以通過另外一種方式來引入命名空間,其實這兩者間都是對等的。
xmlns:i=http://schemas.microsoft.com/expression/2010/interactivity
這里以TextBox的GetFocus和LostFocus為例來進行說明
<TextBox Text="CommandBinding"> <i:Interaction.Triggers> <i:EventTrigger EventName="LostFocus"> <i:InvokeCommandAction Command="{Binding OnTextLostFocus}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type TextBox}}}"/> </i:EventTrigger> <i:EventTrigger EventName="GotFocus"> <i:InvokeCommandAction Command="{Binding OnTextGotFocus}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorLevel=1, AncestorType={x:Type TextBox}}}"/> </i:EventTrigger> </i:Interaction.Triggers> </TextBox>
這個里面我們重點來看看這個InvokeCommandAction的代碼結構
namespace System.Windows.Interactivity { public sealed class InvokeCommandAction : TriggerAction<DependencyObject> { public static readonly DependencyProperty CommandProperty; public static readonly DependencyProperty CommandParameterProperty; public InvokeCommandAction(); public string CommandName { get; set; } public ICommand Command { get; set; } public object CommandParameter { get; set; } protected override void Invoke(object parameter); } }
這里我們發現這里我們如果我們定義一個Command的話我們只能夠在Command中獲取到我們綁定的CommandParameter這個參數,但是有時候我們需要獲取到觸發這個事件的RoutedEventArgs的時候,通過這種方式就很難獲取到了,這個時候我們就需要自己去擴展一個InvokeCommandAction了,這個時候我們應該怎么做呢?整個過程分成三步:
public class ExCommandParameter { /// <summary> /// 事件觸發源 /// </summary> public DependencyObject Sender { get; set; } /// <summary> /// 事件參數 /// </summary> public EventArgs EventArgs { get; set; } /// <summary> /// 額外參數 /// </summary> public object Parameter { get; set; } }
這個對象除了封裝我們常規的參數外還封裝了我們需要的EventArgs屬性,有了這個我們就能將當前的事件的EventArgs傳遞進來了。
public class ExInvokeCommandAction : TriggerAction<DependencyObject> { private string commandName; public static readonly DependencyProperty CommandProperty = DependencyProperty.Register("Command", typeof(ICommand), typeof(ExInvokeCommandAction), null); public static readonly DependencyProperty CommandParameterProperty = DependencyProperty.Register("CommandParameter", typeof(object), typeof(ExInvokeCommandAction), null); /// <summary> /// 獲得或設置此操作應調用的命令的名稱。 /// </summary> /// <value>此操作應調用的命令的名稱。</value> /// <remarks>如果設置了此屬性和 Command 屬性,則此屬性將被后者所取代。</remarks> public string CommandName { get { base.ReadPreamble(); return this.commandName; } set { if (this.CommandName != value) { base.WritePreamble(); this.commandName = value; base.WritePostscript(); } } } /// <summary> /// 獲取或設置此操作應調用的命令。這是依賴屬性。 /// </summary> /// <value>要執行的命令。</value> /// <remarks>如果設置了此屬性和 CommandName 屬性,則此屬性將優先于后者。</remarks> public ICommand Command { get { return (ICommand)base.GetValue(ExInvokeCommandAction.CommandProperty); } set { base.SetValue(ExInvokeCommandAction.CommandProperty, value); } } /// <summary> /// 獲得或設置命令參數。這是依賴屬性。 /// </summary> /// <value>命令參數。</value> /// <remarks>這是傳遞給 ICommand.CanExecute 和 ICommand.Execute 的值。</remarks> public object CommandParameter { get { return base.GetValue(ExInvokeCommandAction.CommandParameterProperty); } set { base.SetValue(ExInvokeCommandAction.CommandParameterProperty, value); } } /// <summary> /// 調用操作。 /// </summary> /// <param name="parameter">操作的參數。如果操作不需要參數,則可以將參數設置為空引用。</param> protected override void Invoke(object parameter) { if (base.AssociatedObject != null) { ICommand command = this.ResolveCommand(); /* * ★★★★★★★★★★★★★★★★★★★★★★★★ * 注意這里添加了事件觸發源和事件參數 * ★★★★★★★★★★★★★★★★★★★★★★★★ */ ExCommandParameter exParameter = new ExCommandParameter { Sender = base.AssociatedObject, Parameter = GetValue(CommandParameterProperty), EventArgs = parameter as EventArgs }; if (command != null && command.CanExecute(exParameter)) { /* * ★★★★★★★★★★★★★★★★★★★★★★★★ * 注意將擴展的參數傳遞到Execute方法中 * ★★★★★★★★★★★★★★★★★★★★★★★★ */ command.Execute(exParameter); } } } private ICommand ResolveCommand() { ICommand result = null; if (this.Command != null) { result = this.Command; } else { if (base.AssociatedObject != null) { Type type = base.AssociatedObject.GetType(); PropertyInfo[] properties = type.GetProperties(BindingFlags.Instance | BindingFlags.Public); PropertyInfo[] array = properties; for (int i = 0; i < array.Length; i++) { PropertyInfo propertyInfo = array[i]; if (typeof(ICommand).IsAssignableFrom(propertyInfo.PropertyType) && string.Equals(propertyInfo.Name, this.CommandName, StringComparison.Ordinal)) { result = (ICommand)propertyInfo.GetValue(base.AssociatedObject, null); } } } } return result; } }
這個里面的重點是要重寫基類中的Invoke方法,將當前命令通過反射的方式來獲取到,然后在執行command.Execute方法的時候將我們自定義的ExCommandParameter傳遞進去,這樣我們就能夠在最終綁定的命令中獲取到特定的EventArgs對象了。
<ListBox x:Name="lb_selecthistorymembers" SnapsToDevicePixels="true" ItemsSource="{Binding DataContext.SpecificHistoryMembers,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=my:AnnouncementApp},Mode=TwoWay}" HorizontalAlignment="Stretch" ScrollViewer.HorizontalScrollBarVisibility="Disabled" Background="#fff" BorderThickness="1"> <i:Interaction.Triggers> <i:EventTrigger EventName="SelectionChanged"> <interactive:ExInvokeCommandAction Command="{Binding DataContext.OnSelectHistoryMembersListBoxSelected,RelativeSource={RelativeSource Mode=FindAncestor,AncestorType=my:AnnouncementApp},Mode=TwoWay}" CommandParameter="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=ListBox}}"> </interactive:ExInvokeCommandAction> </i:EventTrigger> </i:Interaction.Triggers> </ListBox>
注意這里需要首先引入自定義的interactive的命名空間,這個在使用的時候需要注意,另外在最終的Command訂閱中EventArgs根據不同的事件有不同的表現形式,比如Loaded事件,那么最終獲取到的EventArgs就是RoutedEventArgs對象,如果是TableControl的SelectionChanged事件,那么最終獲取到的就是SelectionChangedEventArgs對象,這個在使用的時候需要加以區分。
System.Windows.Interactivity.dll中一個重要的擴展就是對Behavior的擴展,這個Behavior到底該怎么用呢?我們來看下面的一個例子,我們需要給一個TextBlock和Button增加一個統一的DropShadowEffect,我們先來看看最終的效果,然后再就具體的代碼進行分析。
1 增加一個EffectBehavior
public class EffectBehavior : Behavior<FrameworkElement> { protected override void OnAttached() { base.OnAttached(); AssociatedObject.MouseEnter += AssociatedObject_MouseEnter; AssociatedObject.MouseLeave += AssociatedObject_MouseLeave; } private void AssociatedObject_MouseLeave(object sender, System.Windows.Input.MouseEventArgs e) { var element = sender as FrameworkElement; element.Effect = new DropShadowEffect() { Color = Colors.Transparent, ShadowDepth = 2 }; ; } private void AssociatedObject_MouseEnter(object sender, System.Windows.Input.MouseEventArgs e) { var element = sender as FrameworkElement; element.Effect = new DropShadowEffect() { Color = Colors.Red, ShadowDepth = 2 }; } protected override void OnDetaching() { base.OnDetaching(); AssociatedObject.MouseEnter -= AssociatedObject_MouseEnter; AssociatedObject.MouseLeave -= AssociatedObject_MouseLeave; } }
這里我們繼承自System.Windows.Interactivity中的Behavior<T>這個泛型類,這里我們的泛型參數使用FrameworkElement,因為大部分的控件都是繼承自這個對象,我們方便為其統一添加效果,在集成這個基類后我們需要重寫基類的OnAttached和OnDetaching方法,這個里面AssociatedObject就是我們具體添加Effect的元素,在我們的示例中這個分別是TextBlock和Button對象。
2 在具體的控件中添加此效果
<Window x:Class="WpfBehavior.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:local="clr-namespace:WpfBehavior" xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity" mc:Ignorable="d" Title="MainWindow" Height="450" Width="800"> <Grid> <StackPanel Orientation="Vertical" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock Text="測試文本" Margin="2" Height="30"> <i:Interaction.Behaviors> <local:EffectBehavior></local:EffectBehavior> </i:Interaction.Behaviors> </TextBlock> <Button Content="測試" Width="80" Height="30" Margin="2"> <i:Interaction.Behaviors> <local:EffectBehavior></local:EffectBehavior> </i:Interaction.Behaviors> </Button> </StackPanel> </Grid> </Window>
關于System.Windows.Interactivity怎么在c# 項目中使用就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。