Bir Stil Belirleyiciye Karışım Davranışı Nasıl Eklenir


88

Button için bir Karışım davranışı oluşturdum. Bunu uygulamadaki tüm Düğmelerime nasıl ayarlayabilirim?

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

Ancak denediğimde:

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

Hatayı alıyorum

"Davranışlar" özelliği, erişilebilir bir ayarlayıcıya sahip değildir.

Yanıtlar:


76

Aynı sorunu yaşadım ve bir çözüm buldum. Bu soruyu çözdükten sonra buldum ve çözümümün Mark'la çok ortak yönleri olduğunu görüyorum. Ancak bu yaklaşım biraz farklıdır.

Temel sorun, davranışların ve tetikleyicilerin belirli bir nesneyle ilişkilendirilmesi ve bu nedenle birden çok farklı ilişkili nesne için aynı davranış örneğini kullanamamanızdır. Davranışınızı tanımladığınızda satır içi XAML bu bire bir ilişkiyi zorlar. Bununla birlikte, bir stilde bir davranış ayarlamaya çalıştığınızda, stil uygulandığı tüm nesneler için yeniden kullanılabilir ve bu, temel davranış sınıflarında istisnalar atar. Aslında yazarlar, işe yaramayacağını bilerek, bunu yapmaya çalışmamızı önlemek için büyük çaba sarf ettiler.

İlk sorun, yapıcı dahili olduğu için bir davranış belirleyici değeri bile oluşturamayacağımızdır. Bu yüzden kendi davranışımıza ihtiyacımız var ve toplama sınıflarını tetikliyoruz.

Bir sonraki sorun, davranış ve tetikleyici ekli özelliklerin ayarlayıcılara sahip olmaması ve bu nedenle bunlara yalnızca satır içi XAML ile eklenebilmeleridir. Bu sorunu, birincil davranışı işleyen ve özellikleri tetikleyen kendi ekli özelliklerimizle çözüyoruz.

Üçüncü sorun, davranış koleksiyonumuzun yalnızca tek bir stil hedef için iyi olmasıdır. x:Shared="False"Bunu, her başvurulduğunda kaynağın yeni bir kopyasını oluşturan az kullanılan bir XAML özelliğini kullanarak çözüyoruz .

Son sorun, davranışların ve tetikleyicilerin diğer stil belirleyiciler gibi olmamasıdır; eski davranışları yeni davranışlarla değiştirmek istemiyoruz çünkü çılgınca farklı şeyler yapabilirler. Dolayısıyla, bir davranış eklediğinizde onu ortadan kaldıramayacağınızı kabul edersek (ve davranışların şu anda çalışma şekli budur), davranışların ve tetikleyicilerin ilave olması gerektiği sonucuna varabiliriz ve bu, ekli özelliklerimiz tarafından ele alınabilir.

İşte bu yaklaşımı kullanan bir örnek:

<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>

Örnek, tetikleyicileri kullanır ancak davranışlar aynı şekilde çalışır. Örnekte şunları gösteriyoruz:

  • stil birden çok metin bloğuna uygulanabilir
  • çeşitli veri bağlama türlerinin tümü doğru çalışır
  • çıktı penceresinde metin oluşturan bir hata ayıklama eylemi

İşte örnek bir davranış, bizim DebugAction. Daha doğrusu bir eylemdir, ancak dilin kötüye kullanılması yoluyla davranışlar, tetikleyiciler ve eylemlere "davranışlar" diyoruz.

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);
    }
}

Son olarak, tüm bunların çalışmasını sağlamak için koleksiyonlarımız ve ekli mülklerimiz. İle benzer şekilde Interaction.Behaviors, hedeflediğiniz özellik çağrılır SupplementaryInteraction.Behaviorsçünkü bu özelliği ayarlayarak, Interaction.Behaviorstetikleyicilere davranışlar ekleyeceksiniz .

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);
    }
}

ve orada, tamamen işlevsel davranışlar ve stiller aracılığıyla uygulanan tetikleyiciler var.


Harika bir şey, bu çok güzel çalışıyor. Stili örneğin UserControl kaynaklarına koyarsanız, e.NewValue ilk başta boş olabilir (kullanılan kontrole bağlı olabilir - bunu Infragistics XamDataTree'de XamDataTreeNodeControl kullanıyorum). Bu yüzden OnPropertyTriggersChanged: if (e.NewValue! = Null)
MetalMikester

Setter'i örtük bir Tarzda uygularken bu yaklaşımla ilgili bir sorunu olan var mı? Örtük olmayan bir stille (Anahtarlı) iyi çalışmasını sağladım, ancak örtük bir stilde ise döngüsel bir referans istisnası alıyorum.
Jason Frank 13

1
Güzel çözüm, ancak maalesef WinRT'de çalışmıyor çünkü x: Shared bu platformda mevcut değil ...
Thomas Levesque

1
Bu çözümün işe yaradığını onaylayabilirim. Paylaştığınız için çok teşekkür ederim Yine de bunu örtük bir stille denemedim.
Golvellius

2
@Jason Frank, Teşekkürler, Tıpkı diğerleri için referans olarak ... Her iki durumda da çalışmasını sağladım: Örtük ve açık. Aslında, başkalarına yardım etmek için tüm kodumu nereye koyacağımı sorduğum bir soru soruyorum ama biri sorumun bir kopya olduğunu tahmin ediyor. Bulduğum her şeyi vererek kendi soruma cevap veremiyorum. Sanırım oldukça güzel şeyler keşfediyorum. :-( ... Umarım bu davranış diğer kullanıcıları yararlı bilgilerden mahrum bıraktığı için çok sık olmaz.
Eric Ouellet

27

Cevapları özetleyen ve bu harika makale Stillerdeki Davranışları Harmanla , bu genel kısa ve rahat çözüme geldim:

Herhangi bir davranış tarafından miras alınabilecek genel sınıf yaptım.

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());
                }    
            }
        }
    }

Böylece, bunun gibi birçok bileşenle yeniden kullanabilirsiniz:

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

Ve XAML'de şunları beyan edecek kadar:

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

Temel olarak AttachableForStyleBehavior sınıfı xaml şeyler yaptı ve her bileşen için davranış örneğini stilde kaydederek. Daha fazla ayrıntı için lütfen bağlantıya bakın.


Tıkır tıkır çalışıyor! Scrollingbehavior'ımın birleşimiyle, Inner RowDetailsTemplate-Datagrid'lerin üst Datagrid'leri kaydırmamasından kurtuldum.
Philipp Michalski


1
Davranışta bağımlılık özellikleriyle veri bağlamaya ne dersiniz?
JobaDiniz

Kullanıcıyla nasıl iletişime geçeceğimi veya kişisel olarak olumsuz geri bildirimlerle düzenlemeyi nasıl reddedeceğimi bilmiyorum. Sevgili @Der_Meister ve diğer editörler, lütfen düzenlemeyi denemeden önce kodu dikkatlice okuyun. Diğer kullanıcıları ve itibarımı da etkileyebilir. Bu durumda, IsEnabledForStyle özelliğini kaldırarak ve ısrarla statik yöntemlerle değiştirerek, bu sorunun ana noktası olan xaml'de ona bağlanma olasılığını yok etmiş olursunuz. Görünüşe göre sonuna kadar kod okumamışsın. Maalesef düzenlemenizi büyük bir eksi ile reddedemem, bu yüzden lütfen gelecekte dikkatli olun.
Roma Borodov

1
@RomaBorodov, her şey XAML'de çalışıyor. Bu, ekli özelliği tanımlamanın doğru bir yoludur (bağımlılık özelliğinden farklıdır). Belgelere bakın: docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/…
Der_Meister

19

1. Ekli Mülk Oluşturun

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. Bir Davranış Oluşturun

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. Bir Stil oluşturun ve ekli özelliği ayarlayın

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

DependencyProperty'ye stilden erişmeye çalıştığımda IsSingleClickEditMode tanınmıyor veya erişilebilir değil diyor?
Igor Meszaros

Maalesef benim kötü .. en kısa sürede ben GetIsSingleClickEditMode sen DependencyProperty.RegisterAttached için geçmek dize eşleşmesi gerekir fark yorumladı olarak
Igor Meszaros

OnDetaching başka bir olay işleyicisi ekler, bu düzeltilmelidir (bir
gönderiyi

11

Her davranış için ekli bir mülk oluşturmamak için başka bir fikrim var:

  1. Davranış oluşturucu arayüzü:

    public interface IBehaviorCreator
    {
        Behavior Create();
    }
    
  2. Küçük yardımcı koleksiyon:

    public class BehaviorCreatorCollection : Collection<IBehaviorCreator> { }
    
  3. Davranışı ekleyen yardımcı sınıf:

    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. Şimdi, IBehaviorCreator'ı uygulayan davranışınız:

    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. Ve şimdi xaml'de kullan:

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

5

Orijinal makaleyi bulamadım ama etkiyi yeniden yaratabildim.

#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>

Her davranış için bunu yazmak zorunda kalmak biraz PITA olsa da.
Stephen Drew

0

Davranış kodu bir Görsel bekler, bu yüzden onu sadece görsel üzerine ekleyebiliriz. Dolayısıyla görebildiğim tek seçenek, Stile eklenen davranışı elde etmek ve belirli bir denetimin tüm örneğini etkilemek için ControlTemplate içindeki öğelerden birine eklemektir.


0

WPF'de Ekli Davranışlara Giriş makalesi , yalnızca Stil kullanan ekli bir davranışı uygular ve ilgili veya yardımcı olabilir.

"Ekli Davranışlara Giriş" makalesindeki teknik, Stil'i kullanarak Etkileşim etiketlerini tamamen ortadan kaldırır. Bunun sadece daha eski bir teknik olduğu için mi, yoksa bazı senaryolarda tercih edilmesi gereken yerlerde hala bazı faydalar sağladığından mı emin değilim.


2
Bu bir Karışım davranışı değil, basit ekli bir özellik aracılığıyla bir "davranış" tır.
Stephen Drew

0

Roman Dvoskin ve Jonathan Allen'ın bu konudaki yanıtlarının gösterdiği yaklaşımı beğendim. Yine de bu tekniği ilk öğrendiğimde, teknik hakkında daha fazla açıklama sağlayan bu blog yazısından faydalandım . Ve her şeyi bağlam içinde görmek için, işte yazarın blog gönderisinde bahsettiği sınıfın kaynak kodunun tamamı .


0

Bireysel davranışı / tetikleyiciyi Kaynaklar olarak bildirin:

<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>

Bunları koleksiyona ekleyin:

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

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

</Button>

4
OP'ye nasıl cevap veriyor? Tetikleyici, cevabınıza bir stille eklenmedi.
Kryptos

0

Bu cevaba dayanarak daha basit bir çözüm yaptım, sadece tek bir sınıfa ihtiyaç var ve davranışlarınızda başka bir şey uygulamaya gerek yok.

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
}

ve örnek kullanım

<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'i kullanmak için bu xmlns'yi eklemeyi unutmayın:

xmlns:collections="clr-namespace:System.Collections;assembly=mscorlib"
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.