स्टाइल सेटर में ब्लेंड बिहेवियर कैसे जोड़ें


88

मैंने बटन के लिए एक ब्लेंड व्यवहार किया है। मैं ऐप में अपने सभी बटनों को कैसे सेट कर सकता हूं।

<Button ...>
  <i:Interaction.Behaviors>
    <local:MyBehavior />
  </i:Interaction.Behaviors>
</Button>

हालाँकि, जब मैं कोशिश करता हूँ:

<Style>
  <Setter Property="i:Interaction.Behaviors">
    <Setter.Value>
      <local:MyBehavior />
    </Setter.Value>
  </Setter>
</Style>

मुझे त्रुटि मिलती है

संपत्ति "व्यवहार" के पास एक सुलभ सेटर नहीं है।

जवाबों:


76

मुझे एक ही समस्या थी और मैं एक समाधान के साथ आया हूं। मुझे यह प्रश्न हल करने के बाद मिला और मैंने देखा कि मेरा समाधान मार्क के साथ बहुत आम है। हालाँकि, यह दृष्टिकोण थोड़ा अलग है।

मुख्य समस्या यह है कि व्यवहार और ट्रिगर एक विशिष्ट वस्तु के साथ जुड़े होते हैं और इसलिए आप कई अलग-अलग संबद्ध वस्तुओं के लिए व्यवहार के एक ही उदाहरण का उपयोग नहीं कर सकते हैं। जब आप अपने व्यवहार को परिभाषित करते हैं तो 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);
    }
}

और आपके पास यह है, शैलियों के माध्यम से पूरी तरह से कार्यात्मक व्यवहार और ट्रिगर।


महान सामान, यह खूबसूरती से काम करता है। मैंने देखा कि यदि आप शैली को रखते हैं, उदाहरण के लिए, UserControl संसाधनों में, तो e.NewValue पहली बार में अशक्त हो सकता है (उपयोग किए गए नियंत्रण पर निर्भर हो सकता है - मैं एक Infragistics XamDataTree में XamDataTreeNodeCrolrol पर इसका उपयोग कर रहा हूं)। इसलिए मैंने OnPropertyTriggersChanged में थोड़ा सा पवित्रता जाँच जोड़ा: if (e.NewValue! =
Null

क्या किसी को इस तरीके से कोई समस्या है जब सेटर को निहित शैली में लागू किया जाए ? मैंने इसे एक गैर-निहित शैली (एक की के साथ एक) के साथ ठीक काम करने के लिए प्राप्त किया है, लेकिन मुझे एक चक्रीय संदर्भ अपवाद मिलता है यदि इसका निहितार्थ शैली में है।
जेसन फ्रैंक

1
अच्छा समाधान है, लेकिन दुर्भाग्य से यह WinRT में काम नहीं करता है, क्योंकि x: साझा इस मंच पर मौजूद नहीं है ...
थॉमस Levesque

1
मैं पुष्टि कर सकता हूं कि यह समाधान काम करता है। इसे शेयर करने के लिए आपका बहुत-बहुत धन्यवाद। मैंने अभी तक इसे एक अंतर्निहित शैली के साथ आज़माया नहीं है, हालाँकि।
गोलवेलियस

2
@ जेसन फ्रैंक, धन्यवाद, दूसरों के लिए संदर्भ के रूप में ... मैंने इसे दोनों मामलों में काम किया: निहित और स्पष्ट। वास्तव में मैं एक प्रश्न पूछता हूं कि मैंने अपना सारा कोड दूसरों की मदद के लिए कहां रखा होगा, लेकिन किसी ने अनुमान लगाया कि मेरा प्रश्न नकल था। मैं अपने स्वयं के प्रश्न का उत्तर नहीं दे सकता जो मैंने पाया है। मुझे लगता है कि मैं बहुत अच्छी चीजें खोजता हूं। :-( ... मुझे उम्मीद है कि ऐसा अक्सर नहीं होता है क्योंकि यह व्यवहार अन्य उपयोगकर्ताओं को उपयोगी जानकारी से वंचित करता है।
एरिक ओउलेट

27

जवाब और स्टाइल्स में इस शानदार लेख ब्लेंड बिहेवियर , मैं इस जेनेरिक लघु और आश्वस्त समाधान के लिए आया हूं:

मैंने सामान्य वर्ग बनाया, जो किसी भी व्यवहार से विरासत में मिला हो सकता है।

public class AttachableForStyleBehavior<TComponent, TBehavior> : Behavior<TComponent>
        where TComponent : System.Windows.DependencyObject
        where TBehavior : AttachableForStyleBehavior<TComponent, TBehavior> , new ()
    {
        public static DependencyProperty IsEnabledForStyleProperty =
            DependencyProperty.RegisterAttached("IsEnabledForStyle", typeof(bool),
            typeof(AttachableForStyleBehavior<TComponent, TBehavior>), new FrameworkPropertyMetadata(false, OnIsEnabledForStyleChanged)); 

        public bool IsEnabledForStyle
        {
            get { return (bool)GetValue(IsEnabledForStyleProperty); }
            set { SetValue(IsEnabledForStyleProperty, value); }
        }

        private static void OnIsEnabledForStyleChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            UIElement uie = d as UIElement;

            if (uie != null)
            {
                var behColl = Interaction.GetBehaviors(uie);
                var existingBehavior = behColl.FirstOrDefault(b => b.GetType() ==
                      typeof(TBehavior)) as TBehavior;

                if ((bool)e.NewValue == false && existingBehavior != null)
                {
                    behColl.Remove(existingBehavior);
                }

                else if ((bool)e.NewValue == true && existingBehavior == null)
                {
                    behColl.Add(new TBehavior());
                }    
            }
        }
    }

तो आप इसे इस तरह से बहुत सारे घटकों के साथ पुनः उपयोग कर सकते हैं:

public class ComboBoxBehaviour : AttachableForStyleBehavior<ComboBox, ComboBoxBehaviour>
    { ... }

और घोषित करने के लिए XAML में पर्याप्त:

 <Style TargetType="ComboBox">
            <Setter Property="behaviours:ComboBoxBehaviour.IsEnabledForStyle" Value="True"/>

इसलिए मूल रूप से AttachableForStyleBehavior वर्ग ने शैली में प्रत्येक घटक के लिए व्यवहार की आवृत्ति को पंजीकृत करते हुए, xaml चीजें बनाईं। अधिक जानकारी के लिए, कृपया लिंक देखें।


एक जादू की तरह काम करता है! मेरे स्क्रॉलिंगबेहवियर के साथ मुझे इनर रोवडेट्स से छुटकारा मिला।
फिलिप माइकल्स्की

खुशी में मदद करने के लिए, आनंद =)
रोमा बोरोडोव

1
व्यवहार में निर्भरता गुणों के साथ डेटा बाइंडिंग के बारे में क्या?
जोबाडाइनिज

मुझे नहीं पता कि उपयोगकर्ता से कैसे संपर्क करें या व्यक्तिगत प्रतिक्रिया के साथ नकारात्मक प्रतिक्रिया को संपादित करें। तो प्रिय @Der_Meister और अन्य संपादकों, कृपया इसे संपादित करने का प्रयास करने से पहले कोड को ध्यान से पढ़ें। यह अन्य उपयोगकर्ताओं और मेरी प्रतिष्ठा को भी प्रभावित कर सकता है। इस मामले में, IsEnabledForStyle संपत्ति को हटाकर और इसे स्थिर तरीकों से बदलने के लिए, आप इसे xaml में बांधने की संभावना को नष्ट कर देते हैं, जो इस प्रश्न का मुख्य बिंदु है। तो ऐसा लगता है कि आपने अंत तक कोड नहीं पढ़ा है। अफसोस की बात है कि मैं आपके संपादन को बड़े ऋण के साथ अस्वीकार नहीं कर सकता, इसलिए कृपया भविष्य में सावधान रहें।
रोमा बोरोडोव

1
@RomaBorodov, XAML में सब कुछ काम करता है। यह संलग्न संपत्ति को परिभाषित करने का एक सही तरीका है (जो निर्भरता संपत्ति से अलग है)। प्रलेखन देखें: docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/…
Der_Meister

19

1.Create संलग्न संपत्ति

public static class DataGridCellAttachedProperties
{
    //Register new attached property
    public static readonly DependencyProperty IsSingleClickEditModeProperty =
        DependencyProperty.RegisterAttached("IsSingleClickEditMode", typeof(bool), typeof(DataGridCellAttachedProperties), new UIPropertyMetadata(false, OnPropertyIsSingleClickEditModeChanged));

    private static void OnPropertyIsSingleClickEditModeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var dataGridCell = d as DataGridCell;
        if (dataGridCell == null)
            return;

        var isSingleEditMode = GetIsSingleClickEditMode(d);
        var behaviors =  Interaction.GetBehaviors(d);
        var singleClickEditBehavior = behaviors.SingleOrDefault(x => x is SingleClickEditDataGridCellBehavior);

        if (singleClickEditBehavior != null && !isSingleEditMode)
            behaviors.Remove(singleClickEditBehavior);
        else if (singleClickEditBehavior == null && isSingleEditMode)
        {
            singleClickEditBehavior = new SingleClickEditDataGridCellBehavior();
            behaviors.Add(singleClickEditBehavior);
        }
    }

    public static bool GetIsSingleClickEditMode(DependencyObject obj)
    {
        return (bool) obj.GetValue(IsSingleClickEditModeProperty);
    }

    public static void SetIsSingleClickEditMode(DependencyObject obj, bool value)
    {
        obj.SetValue(IsSingleClickEditModeProperty, value);
    }
}

2. एक व्यवहार बनाएँ

public class SingleClickEditDataGridCellBehavior:Behavior<DataGridCell>
        {
            protected override void OnAttached()
            {
                base.OnAttached();
                AssociatedObject.PreviewMouseLeftButtonDown += DataGridCellPreviewMouseLeftButtonDown;
            }

            protected override void OnDetaching()
            {
                base.OnDetaching();
                AssociatedObject.PreviewMouseLeftButtonDown += DataGridCellPreviewMouseLeftButtonDown;
            }

            void DataGridCellPreviewMouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
            {
                 DataGridCell cell = sender as DataGridCell;
                if (cell != null && !cell.IsEditing && !cell.IsReadOnly)
                {
                    if (!cell.IsFocused)
                    {
                        cell.Focus();
                    }
                    DataGrid dataGrid = LogicalTreeWalker.FindParentOfType<DataGrid>(cell); //FindVisualParent<DataGrid>(cell);
                    if (dataGrid != null)
                    {
                        if (dataGrid.SelectionUnit != DataGridSelectionUnit.FullRow)
                        {
                            if (!cell.IsSelected)
                                cell.IsSelected = true;
                        }
                        else
                        {
                            DataGridRow row =  LogicalTreeWalker.FindParentOfType<DataGridRow>(cell); //FindVisualParent<DataGridRow>(cell);
                            if (row != null && !row.IsSelected)
                            {
                                row.IsSelected = true;
                            }
                        }
                    }
                }
            }    
        }

3. एक शैली बनाएँ और संलग्न संपत्ति सेट करें

        <Style TargetType="{x:Type DataGridCell}">
            <Setter Property="Behaviors:DataGridCellAttachedProperties.IsSingleClickEditMode" Value="True"/>
        </Style>

जब मैं इस शैली से डिपेंडेंसीप्रॉपर्टी तक पहुंचने की कोशिश करता हूं तो यह कहता है कि IsSingleClickEditMode मान्यता प्राप्त नहीं है या सुलभ नहीं है?
इगोर मेस्सरोस

क्षमा करें मेरा बुरा .. जैसे ही मैंने टिप्पणी की मुझे एहसास हुआ GetIsSingleClickEditMode स्ट्रिंग आप DependencyProperty.RegisterAttached करने के लिए पारित मैच चाहिए
इगोर मेस्ज़ारोस

OnDetaching एक अन्य ईवेंट हैंडलर जोड़ता है, इसे ठीक किया जाना चाहिए (पोस्ट को संपादित करते समय किसी एकल वर्ण को संशोधित नहीं किया जा सकता ...)
BalintPogatsa

11

मेरे पास एक और विचार है, प्रत्येक व्यवहार के लिए संलग्न संपत्ति के निर्माण से बचने के लिए:

  1. व्यवहार निर्माता इंटरफ़ेस:

    public interface IBehaviorCreator
    {
        Behavior Create();
    }
    
  2. छोटे सहायक संग्रह:

    public class BehaviorCreatorCollection : Collection<IBehaviorCreator> { }
    
  3. हेल्पर वर्ग जो व्यवहार को संलग्न करता है:

    public static class BehaviorInStyleAttacher
    {
        #region Attached Properties
    
        public static readonly DependencyProperty BehaviorsProperty =
            DependencyProperty.RegisterAttached(
                "Behaviors",
                typeof(BehaviorCreatorCollection),
                typeof(BehaviorInStyleAttacher),
                new UIPropertyMetadata(null, OnBehaviorsChanged));
    
        #endregion
    
        #region Getter and Setter of Attached Properties
    
        public static BehaviorCreatorCollection GetBehaviors(TreeView treeView)
        {
            return (BehaviorCreatorCollection)treeView.GetValue(BehaviorsProperty);
        }
    
        public static void SetBehaviors(
            TreeView treeView, BehaviorCreatorCollection value)
        {
            treeView.SetValue(BehaviorsProperty, value);
        }
    
        #endregion
    
        #region on property changed methods
    
        private static void OnBehaviorsChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
        {
            if (e.NewValue is BehaviorCreatorCollection == false)
                return;
    
            BehaviorCreatorCollection newBehaviorCollection = e.NewValue as BehaviorCreatorCollection;
    
            BehaviorCollection behaviorCollection = Interaction.GetBehaviors(depObj);
            behaviorCollection.Clear();
            foreach (IBehaviorCreator behavior in newBehaviorCollection)
            {
                behaviorCollection.Add(behavior.Create());
            }
        }
    
        #endregion
    }
    
  4. अब आपका व्यवहार, जो IBehaororCreator को लागू करता है:

    public class SingleClickEditDataGridCellBehavior:Behavior<DataGridCell>, IBehaviorCreator
    {
        //some code ...
    
        public Behavior Create()
        {
            // here of course you can also set properties if required
            return new SingleClickEditDataGridCellBehavior();
        }
    }
    
  5. और अब इसे xaml में उपयोग करें:

    <Style TargetType="{x:Type DataGridCell}">
      <Setter Property="helper:BehaviorInStyleAttacher.Behaviors" >
        <Setter.Value>
          <helper:BehaviorCreatorCollection>
            <behaviors:SingleClickEditDataGridCellBehavior/>
          </helper:BehaviorCreatorCollection>
        </Setter.Value>
      </Setter>
    </Style>
    

5

मुझे मूल लेख नहीं मिला लेकिन मैं प्रभाव को फिर से बनाने में सक्षम था।

#region Attached Properties Boilerplate

    public static readonly DependencyProperty IsActiveProperty = DependencyProperty.RegisterAttached("IsActive", typeof(bool), typeof(ScrollIntoViewBehavior), new PropertyMetadata(false, OnIsActiveChanged));

    public static bool GetIsActive(FrameworkElement control)
    {
        return (bool)control.GetValue(IsActiveProperty);
    }

    public static void SetIsActive(
      FrameworkElement control, bool value)
    {
        control.SetValue(IsActiveProperty, value);
    }

    private static void OnIsActiveChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var behaviors = Interaction.GetBehaviors(d);
        var newValue = (bool)e.NewValue;

        if (newValue)
        {
            //add the behavior if we don't already have one
            if (!behaviors.OfType<ScrollIntoViewBehavior>().Any())
            {
                behaviors.Add(new ScrollIntoViewBehavior());
            }
        }
        else
        {
            //remove any instance of the behavior. (There should only be one, but just in case.)
            foreach (var item in behaviors.ToArray())
            {
                if (item is ScrollIntoViewBehavior)
                    behaviors.Remove(item);
            }
        }
    }


    #endregion
<Style TargetType="Button">
    <Setter Property="Blah:ScrollIntoViewBehavior.IsActive" Value="True" />
</Style>

हालांकि प्रत्येक व्यवहार के लिए यह लिखना थोड़ा पीटा है।
स्टीफन ड्र्यू

0

व्यवहार कोड एक दृश्य की अपेक्षा करता है, इसलिए हम इसे केवल एक दृश्य पर जोड़ सकते हैं। तो एकमात्र विकल्प जो मैं देख सकता था, वह है कंट्रोलटेम्पलेट के अंदर के किसी एक तत्व को जोड़ना ताकि व्यवहार को स्टाइल में जोड़ा जा सके और किसी विशेष नियंत्रण के सभी उदाहरणों को प्रभावित किया जा सके।


0

WPF में संलग्न व्यवहार का परिचय लेख केवल स्टाइल का उपयोग करके संलग्न व्यवहार को लागू करता है, और संबंधित या सहायक भी हो सकता है।

"इंट्रोडक्टेड टू अटैच्ड बिहेवियर" लेख में तकनीक पूरी तरह से स्टाइल पर प्रयोग करके इंटरएक्टिविटी टैग से बचती है। मुझे नहीं पता कि यह सिर्फ इसलिए है क्योंकि यह एक अधिक दिनांकित तकनीक है, या, अगर यह अभी भी कुछ लाभ प्रदान करता है जहां किसी को कुछ परिदृश्यों में इसे पसंद करना चाहिए।


2
यह एक ब्लेंड व्यवहार नहीं है, यह एक साधारण संलग्न संपत्ति के माध्यम से एक "व्यवहार" है।
स्टीफन ड्रू

0

मुझे इस धागे में रोमन ड्वॉस्किन और जोनाथन एलन के उत्तरों द्वारा दिखाए गए दृष्टिकोण पसंद हैं। जब मैं पहली बार उस तकनीक को सीख रहा था, तो मुझे इस ब्लॉग पोस्ट से लाभ हुआ जो तकनीक के बारे में अधिक व्याख्या प्रदान करता है। और संदर्भ में सब कुछ देखने के लिए, लेखक ने अपने ब्लॉग पोस्ट में जिस वर्ग के बारे में बात की है, उसके लिए यहां संपूर्ण स्रोत कोड है


0

व्यक्तिगत व्यवहार घोषित करें / संसाधन के रूप में ट्रिगर करें:

<Window.Resources>

    <i:EventTrigger x:Key="ET1" EventName="Click">
        <ei:ChangePropertyAction PropertyName="Background">
            <ei:ChangePropertyAction.Value>
                <SolidColorBrush Color="#FFDAD32D"/>
            </ei:ChangePropertyAction.Value>
        </ei:ChangePropertyAction>
    </i:EventTrigger>

</Window.Resources>

उन्हें संग्रह में सम्मिलित करें:

<Button x:Name="Btn1" Content="Button">

        <i:Interaction.Triggers>
             <StaticResourceExtension ResourceKey="ET1"/>
        </i:Interaction.Triggers>

</Button>

4
यह ओपी को कैसे जवाब देता है? ट्रिगर आपके उत्तर में एक शैली के माध्यम से नहीं जोड़ा गया है।
क्रिप्टोस

0

इस उत्तर के आधार पर मैंने एक सरल समाधान किया, जिसमें केवल एक वर्ग की आवश्यकता थी और आपके व्यवहार में कुछ और लागू करने की आवश्यकता नहीं है।

public static class BehaviorInStyleAttacher
{
    #region Attached Properties

    public static readonly DependencyProperty BehaviorsProperty =
        DependencyProperty.RegisterAttached(
            "Behaviors",
            typeof(IEnumerable),
            typeof(BehaviorInStyleAttacher),
            new UIPropertyMetadata(null, OnBehaviorsChanged));

    #endregion

    #region Getter and Setter of Attached Properties

    public static IEnumerable GetBehaviors(DependencyObject dependencyObject)
    {
        return (IEnumerable)dependencyObject.GetValue(BehaviorsProperty);
    }

    public static void SetBehaviors(
        DependencyObject dependencyObject, IEnumerable value)
    {
        dependencyObject.SetValue(BehaviorsProperty, value);
    }

    #endregion

    #region on property changed methods

    private static void OnBehaviorsChanged(DependencyObject depObj, DependencyPropertyChangedEventArgs e)
    {
        if (e.NewValue is IEnumerable == false)
            return;

        var newBehaviorCollection = e.NewValue as IEnumerable;

        BehaviorCollection behaviorCollection = Interaction.GetBehaviors(depObj);
        behaviorCollection.Clear();
        foreach (Behavior behavior in newBehaviorCollection)
        {
            // you need to make a copy of behavior in order to attach it to several controls
            var copy = behavior.Clone() as Behavior;
            behaviorCollection.Add(copy);
        }
    }

    #endregion
}

और नमूना उपयोग है

<Style TargetType="telerik:RadComboBox" x:Key="MultiPeriodSelectableRadComboBox">
    <Setter Property="AllowMultipleSelection" Value="True" />
    <Setter Property="behaviors:BehaviorInStyleAttacher.Behaviors">
        <Setter.Value>
            <collections:ArrayList>
                <behaviors:MultiSelectRadComboBoxBehavior
                        SelectedItems="{Binding SelectedPeriods}"
                        DelayUpdateUntilDropDownClosed="True"
                        SortSelection="True" 
                        ReverseSort="True" />
            </collections:ArrayList>
        </Setter.Value>
    </Setter>
</Style>

ArrayList का उपयोग करने के लिए इस xmlns को जोड़ना न भूलें:

xmlns:collections="clr-namespace:System.Collections;assembly=mscorlib"
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.