मुझे एक ही समस्या थी और मैं एक समाधान के साथ आया हूं। मुझे यह प्रश्न हल करने के बाद मिला और मैंने देखा कि मेरा समाधान मार्क के साथ बहुत आम है। हालाँकि, यह दृष्टिकोण थोड़ा अलग है।
मुख्य समस्या यह है कि व्यवहार और ट्रिगर एक विशिष्ट वस्तु के साथ जुड़े होते हैं और इसलिए आप कई अलग-अलग संबद्ध वस्तुओं के लिए व्यवहार के एक ही उदाहरण का उपयोग नहीं कर सकते हैं। जब आप अपने व्यवहार को परिभाषित करते हैं तो XAML इस एक-से-एक संबंध को लागू करता है। हालाँकि, जब आप किसी शैली में व्यवहार सेट करने का प्रयास करते हैं, तो शैली को उन सभी वस्तुओं के लिए फिर से उपयोग किया जा सकता है जो इसे लागू करते हैं और यह आधार व्यवहार कक्षाओं में अपवादों को फेंक देगा। वास्तव में, लेखक यह जानने के लिए कि यह काम नहीं करेगा, हमें ऐसा करने से रोकने के लिए काफी प्रयास करने गए।
पहली समस्या यह है कि हम एक व्यवहार सेटर वैल्यू भी नहीं बना सकते क्योंकि कंस्ट्रक्टर आंतरिक है। इसलिए हमें अपने स्वयं के व्यवहार और ट्रिगर संग्रह कक्षाओं की आवश्यकता है।
अगली समस्या यह है कि व्यवहार और ट्रिगर संलग्न गुणों में बसने वाले नहीं हैं और इसलिए उन्हें केवल इन-लाइन XAML के साथ जोड़ा जा सकता है। यह समस्या हम अपने स्वयं के संलग्न गुणों के साथ हल करते हैं जो प्राथमिक व्यवहार और ट्रिगर गुणों में हेरफेर करते हैं।
तीसरी समस्या यह है कि हमारा व्यवहार संग्रह केवल एकल शैली के लक्ष्य के लिए अच्छा है। यह हम एक छोटे से इस्तेमाल किए गए XAML सुविधा का उपयोग करके हल करते हैं x:Shared="False"
जो कि संदर्भित होने पर हर बार संसाधन की एक नई प्रतिलिपि बनाता है।
अंतिम समस्या यह है कि व्यवहार और ट्रिगर अन्य शैली बसने वालों की तरह नहीं हैं; हम पुराने व्यवहारों को नए व्यवहारों से बदलना नहीं चाहते क्योंकि वे बेतहाशा अलग-अलग काम कर सकते थे। इसलिए यदि हम स्वीकार करते हैं कि एक बार आप एक व्यवहार जोड़ लेते हैं तो आप उसे दूर नहीं कर सकते हैं (और वर्तमान में जिस तरह से व्यवहार करते हैं), हम यह निष्कर्ष निकाल सकते हैं कि व्यवहार और ट्रिगर एडिटिव होने चाहिए और यह हमारे संलग्न गुणों द्वारा नियंत्रित किया जा सकता है।
यहाँ इस दृष्टिकोण का उपयोग कर एक नमूना है:
<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>
उदाहरण ट्रिगर्स का उपयोग करता है लेकिन व्यवहार उसी तरह काम करते हैं। उदाहरण में, हम दिखाते हैं:
- शैली को कई टेक्स्ट ब्लॉक पर लागू किया जा सकता है
- कई प्रकार के डेटा बाइंडिंग सभी सही ढंग से काम करते हैं
- डिबग एक्शन जो आउटपुट विंडो में टेक्स्ट उत्पन्न करता है
यहाँ एक उदाहरण व्यवहार है, हमारे DebugAction
। अधिक ठीक से यह एक क्रिया है लेकिन भाषा के दुरुपयोग के माध्यम से हम व्यवहार, ट्रिगर और क्रियाओं को "व्यवहार" कहते हैं।
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);
}
}
अंत में, यह सब काम करने के लिए हमारे संग्रह और संलग्न गुण। इसके अनुरूप Interaction.Behaviors
, आपके द्वारा लक्षित संपत्ति को कहा जाता है SupplementaryInteraction.Behaviors
क्योंकि इस संपत्ति को सेट करके, आप व्यवहारों को जोड़ देंगे Interaction.Behaviors
और इसी तरह ट्रिगर्स के लिए।
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);
}
}
और आपके पास यह है, शैलियों के माध्यम से पूरी तरह से कार्यात्मक व्यवहार और ट्रिगर।