Saya memiliki masalah yang sama dan saya telah menemukan solusinya. Saya menemukan pertanyaan ini setelah saya menyelesaikannya dan saya melihat bahwa solusi saya memiliki banyak kesamaan dengan Mark. Namun, pendekatan ini sedikit berbeda.
Masalah utamanya adalah bahwa perilaku dan pemicu terkait dengan objek tertentu, sehingga Anda tidak dapat menggunakan contoh perilaku yang sama untuk beberapa objek terkait yang berbeda. Ketika Anda mendefinisikan perilaku Anda sebaris XAML memberlakukan hubungan satu-ke-satu ini. Namun, saat Anda mencoba menyetel perilaku dalam sebuah gaya, gaya tersebut dapat digunakan kembali untuk semua objek yang diterapkan padanya dan ini akan memunculkan pengecualian di kelas perilaku dasar. Sebenarnya para penulis berusaha keras untuk mencegah kami mencoba melakukan ini, mengetahui bahwa itu tidak akan berhasil.
Masalah pertama adalah bahwa kita bahkan tidak dapat membuat nilai penyetel perilaku karena konstruktornya internal. Jadi kita membutuhkan perilaku kita sendiri dan memicu kelas pengumpulan.
Masalah berikutnya adalah bahwa perilaku dan pemicu properti terlampir tidak memiliki penyetel sehingga mereka hanya dapat ditambahkan ke dengan XAML sebaris. Masalah ini kami selesaikan dengan properti terlampir kami sendiri yang memanipulasi perilaku utama dan properti pemicu.
Masalah ketiga adalah bahwa koleksi perilaku kita hanya bagus untuk satu target gaya. Ini kami selesaikan dengan memanfaatkan fitur XAML yang jarang digunakan x:Shared="False"
yang membuat salinan baru dari sumber daya setiap kali direferensikan.
Masalah terakhir adalah bahwa perilaku dan pemicu tidak seperti penentu gaya lainnya; kami tidak ingin mengganti perilaku lama dengan perilaku baru karena mereka dapat melakukan hal yang sangat berbeda. Jadi, jika kami menerima bahwa setelah Anda menambahkan perilaku, Anda tidak dapat menghilangkannya (dan begitulah cara perilaku saat ini), kami dapat menyimpulkan bahwa perilaku dan pemicu harus bersifat aditif dan ini dapat ditangani oleh properti terlampir kami.
Berikut adalah contoh yang menggunakan pendekatan ini:
<Grid>
<Grid.Resources>
<sys:String x:Key="stringResource1">stringResource1</sys:String>
<local:Triggers x:Key="debugTriggers" x:Shared="False">
<i:EventTrigger EventName="MouseLeftButtonDown">
<local:DebugAction Message="DataContext: {0}" MessageParameter="{Binding}"/>
<local:DebugAction Message="ElementName: {0}" MessageParameter="{Binding Text, ElementName=textBlock2}"/>
<local:DebugAction Message="Mentor: {0}" MessageParameter="{Binding Text, RelativeSource={RelativeSource AncestorType={x:Type FrameworkElement}}}"/>
</i:EventTrigger>
</local:Triggers>
<Style x:Key="debugBehavior" TargetType="FrameworkElement">
<Setter Property="local:SupplementaryInteraction.Triggers" Value="{StaticResource debugTriggers}"/>
</Style>
</Grid.Resources>
<StackPanel DataContext="{StaticResource stringResource1}">
<TextBlock Name="textBlock1" Text="textBlock1" Style="{StaticResource debugBehavior}"/>
<TextBlock Name="textBlock2" Text="textBlock2" Style="{StaticResource debugBehavior}"/>
<TextBlock Name="textBlock3" Text="textBlock3" Style="{StaticResource debugBehavior}"/>
</StackPanel>
</Grid>
Contoh tersebut menggunakan pemicu tetapi perilaku bekerja dengan cara yang sama. Dalam contoh, kami menunjukkan:
- gaya dapat diterapkan ke beberapa blok teks
- beberapa jenis data binding semuanya bekerja dengan benar
- tindakan debug yang menghasilkan teks di jendela keluaran
Berikut adalah contoh perilaku kami DebugAction
. Lebih tepatnya ini adalah suatu tindakan tetapi melalui penyalahgunaan bahasa kita menyebut perilaku, pemicu, dan tindakan "perilaku".
public class DebugAction : TriggerAction<DependencyObject>
{
public string Message
{
get { return (string)GetValue(MessageProperty); }
set { SetValue(MessageProperty, value); }
}
public static readonly DependencyProperty MessageProperty =
DependencyProperty.Register("Message", typeof(string), typeof(DebugAction), new UIPropertyMetadata(""));
public object MessageParameter
{
get { return (object)GetValue(MessageParameterProperty); }
set { SetValue(MessageParameterProperty, value); }
}
public static readonly DependencyProperty MessageParameterProperty =
DependencyProperty.Register("MessageParameter", typeof(object), typeof(DebugAction), new UIPropertyMetadata(null));
protected override void Invoke(object parameter)
{
Debug.WriteLine(Message, MessageParameter, AssociatedObject, parameter);
}
}
Akhirnya, koleksi kami dan properti terlampir membuat ini semua berfungsi. Dengan analogi Interaction.Behaviors
, properti yang Anda targetkan dipanggil SupplementaryInteraction.Behaviors
karena dengan menyetel properti ini, Anda akan menambahkan perilaku Interaction.Behaviors
dan begitu juga untuk pemicu.
public class Behaviors : List<Behavior>
{
}
public class Triggers : List<TriggerBase>
{
}
public static class SupplementaryInteraction
{
public static Behaviors GetBehaviors(DependencyObject obj)
{
return (Behaviors)obj.GetValue(BehaviorsProperty);
}
public static void SetBehaviors(DependencyObject obj, Behaviors value)
{
obj.SetValue(BehaviorsProperty, value);
}
public static readonly DependencyProperty BehaviorsProperty =
DependencyProperty.RegisterAttached("Behaviors", typeof(Behaviors), typeof(SupplementaryInteraction), new UIPropertyMetadata(null, OnPropertyBehaviorsChanged));
private static void OnPropertyBehaviorsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var behaviors = Interaction.GetBehaviors(d);
foreach (var behavior in e.NewValue as Behaviors) behaviors.Add(behavior);
}
public static Triggers GetTriggers(DependencyObject obj)
{
return (Triggers)obj.GetValue(TriggersProperty);
}
public static void SetTriggers(DependencyObject obj, Triggers value)
{
obj.SetValue(TriggersProperty, value);
}
public static readonly DependencyProperty TriggersProperty =
DependencyProperty.RegisterAttached("Triggers", typeof(Triggers), typeof(SupplementaryInteraction), new UIPropertyMetadata(null, OnPropertyTriggersChanged));
private static void OnPropertyTriggersChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var triggers = Interaction.GetTriggers(d);
foreach (var trigger in e.NewValue as Triggers) triggers.Add(trigger);
}
}
dan begitulah, perilaku dan pemicu yang berfungsi penuh diterapkan melalui gaya.