스타일 설정 기에서 블렌드 비헤이비어를 추가하는 방법


88

Button에 대한 Blend 동작을 만들었습니다. 앱의 모든 버튼에 어떻게 설정할 수 있습니까?

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

그러나 내가 시도 할 때 :

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

오류가 발생합니다

"Behaviors"속성에 액세스 할 수있는 setter가 없습니다.

답변:


76

나는 같은 문제가 있었고 해결책을 찾았습니다. 이 질문을 해결 한 후이 질문을 찾았고 내 솔루션이 Mark와 많은 공통점이 있음을 알았습니다. 그러나이 접근 방식은 약간 다릅니다.

주요 문제는 동작과 트리거가 특정 개체와 연결되어 있으므로 여러 다른 연결된 개체에 대해 동일한 동작 인스턴스를 사용할 수 없다는 것입니다. 동작을 정의 할 때 인라인 XAML은이 일대일 관계를 적용합니다. 그러나 스타일에서 비헤이비어를 설정하려고하면 스타일이 적용되는 모든 객체에 대해 재사용 될 수 있으며 기본 비헤이비어 클래스에서 예외가 발생합니다. 사실 저자들은 우리가이 작업을 시도하는 것을 막기 위해 상당한 노력을 기울였습니다.

첫 번째 문제는 생성자가 내부이기 때문에 동작 setter 값을 구성 할 수도 없다는 것입니다. 그래서 우리는 우리 자신의 행동과 트리거 컬렉션 클래스가 필요합니다.

다음 문제는 동작 및 트리거 연결된 속성에 setter가 없으므로 인라인 XAML로만 추가 할 수 있다는 것입니다. 이 문제는 기본 동작을 조작하고 속성을 트리거하는 자체 연결된 속성으로 해결합니다.

세 번째 문제는 비헤이비어 컬렉션이 단일 스타일 대상에만 적합하다는 것입니다. 이 문제 x:Shared="False"는 참조 할 때마다 리소스의 새 복사본을 만드는 거의 사용되지 않는 XAML 기능 을 활용하여 해결합니다 .

마지막 문제는 동작과 트리거가 다른 스타일 설정자와 같지 않다는 것입니다. 우리는 이전 행동을 새로운 행동으로 바꾸고 싶지 않습니다. 왜냐하면 그들은 매우 다른 일을 할 수 있기 때문입니다. 따라서 일단 동작을 추가 한 후에는 제거 할 수 없다는 것을 받아 들인다면 (현재 동작이 작동하는 방식입니다), 동작과 트리거가 추가되어야하며 연결된 속성에 의해 처리 될 수 있다는 결론을 내릴 수 있습니다.

다음은이 접근 방식을 사용하는 샘플입니다.

<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가 처음에는 null이 될 수 있음을 알았습니다 (사용 된 컨트롤에 따라 다를 수 있습니다-Infragistics XamDataTree의 XamDataTreeNodeControl에서 이것을 사용하고 있습니다). 그래서 OnPropertyTriggersChanged에 약간의 온 전성 검사를 추가했습니다. if (e.NewValue! = null)
— MetalMikester 2011

암시 적 스타일 에서 Setter를 적용 할 때이 접근 방식에 문제가있는 사람이 있습니까? 비암 시적 스타일 (키가있는 스타일)에서 제대로 작동하도록했지만 암시 적 스타일이면 순환 참조 예외가 발생합니다.
— Jason Frank

1
니스 솔루션,하지만 불행히도 그것을하지 WinRT에서하지 작업, X 때문에 : 공유가이 플랫폼에 존재하지 않는 ...
— 토마스 레베

1
이 솔루션이 작동하는지 확인할 수 있습니다. 공유해 주셔서 대단히 감사합니다. 나는 아직 암묵적인 스타일로 시도하지 않았습니다.
— Golvellius 2013 년

2
@Jason Frank, 감사합니다. 다른 사람에 대한 참조처럼 ... 두 가지 경우 모두에서 작동하도록 만들었습니다 : 암시 적 및 명시 적. 사실 나는 다른 사람들을 돕기 위해 내 모든 코드를 어디에 두 었는지 질문하지만 누군가 내 질문이 중복되었다고 추정합니다. 나는 내가 찾은 모든 것을주는 내 질문에 답할 수 없다. 꽤 좋은 것을 발견 한 것 같아요. :-( ... 나는 그것이 너무 자주 그 행동이 유용한 정보를 다른 사용자가 박탈하기 때문에 발생하지 않습니다 바랍니다.
— 에릭 Ouellet

27

답변과이 훌륭한 기사 Blend Behaviors in Styles를 요약하면 다음과 같은 짧고 편리한 솔루션에 도달했습니다.

나는 어떤 행동으로도 상속 될 수있는 제네릭 클래스를 만들었다.

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을 만들어 각 구성 요소의 동작 인스턴스를 스타일로 등록합니다. 자세한 내용은 링크를 참조하십시오.


매력처럼 작동합니다! 내 Scrollingbehavior를 결합하면 부모 Datagrid를 스크롤하지 않는 Inner RowDetailsTemplate-Datagrids를 제거했습니다.
— Philipp Michalski 2015

기꺼이 도와) = 즐길
— 로마 Borodov

1
Behavior에서 종속성 속성을 사용한 데이터 바인딩은 어떻습니까?
— JobaDiniz

개인적으로 사용자에게 연락하거나 부정적인 피드백으로 편집을 거부하는 방법을 모르겠습니다. @Der_Meister 및 기타 편집자 여러분, 편집하기 전에 코드를주의 깊게 읽어 보시기 바랍니다. 다른 사용자와 내 평판에도 영향을 미칠 수 있습니다. 이 경우 IsEnabledForStyle 속성을 제거하고이를 정적 메서드로 지속적으로 대체하면이 질문의 요점 인 xaml에서 속성에 바인딩 할 가능성이 없어집니다. 끝까지 코드를 읽지 않은 것 같습니다. Saddly 대단한 마이너스로 편집을 거부 할 수 없으니 앞으로도 조심해주세요.
— Roma Borodov 2018

1
@RomaBorodov, 모든 것이 XAML에서 작동합니다. 연결된 속성을 정의하는 올바른 방법입니다 (종속 속성과 다름). 설명서 참조 : docs.microsoft.com/en-us/dotnet/framework/wpf/advanced/…
— Der_Meister

19

1. 첨부 속성 생성

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 생성 및 연결된 속성 설정

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

스타일에서 DependencyProperty에 액세스하려고하면 IsSingleClickEditMode가 인식되지 않거나 액세스 할 수 없다고 표시됩니까?
— Igor Meszaros

죄송합니다 나의 나쁜 ... 곧 내가 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. 이제 IBehaviorCreator를 구현하는 동작 :

    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>

각 행동에 대해 이것을 작성하는 것은 약간의 PITA입니다.
— Stephen Drew 2012

0

비헤이비어 코드에는 Visual이 필요하므로 시각적 개체에만 추가 할 수 있습니다. 따라서 내가 볼 수있는 유일한 옵션은 스타일에 동작을 추가하고 특정 컨트롤의 모든 인스턴스에 영향을 미치도록 ControlTemplate 내부의 요소 중 하나에 추가하는 것입니다.


0

WPF의 연결된 동작 소개 문서 는 스타일 만 사용하여 연결된 동작을 구현하며 관련되거나 도움이 될 수도 있습니다.

"Introduction to Attached Behaviors"기사의 기술은 on Style을 사용하여 상호 작용 태그를 모두 피합니다. 이것이 더 오래된 기술이기 때문인지 또는 일부 시나리오에서 선호해야하는 몇 가지 이점이 여전히 부여되는지 여부는 알 수 없습니다.


2
이것은 Blend 비헤이비어가 아니라 간단한 연결된 속성을 통한 "비헤이비어"입니다.
— Stephen Drew 2012


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
OP에 어떻게 대답합니까? 방아쇠는 답변의 스타일을 통해 추가되지 않습니다.
— Kryptos

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"
당사 사이트를 사용함과 동시에 당사의 쿠키 정책과 개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.