Search code examples
wpfeventsmvvmattached-properties

How to handle attached properties events?


I created an expander style that contains a checkbox in its header. The checkbox state is bound to an attached property:

<Style TargetType="{x:Type Expander}" x:Key="MyCheckboxExpander">
    <Setter Property="Template">
         <Setter.Value>
              <ControlTemplate TargetType="{x:Type Expander}">
               (...)
                   <CheckBox x:Name="ExpanderHeaderChk" VerticalAlignment="Center" Margin="4,0,0,2" 
                                          IsChecked="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=(my:AP.IsChecked)}" />
                (...)

I my view, inside the expander I have a stackpanel with a ComboBox.

Whenever the user checks the expander's checkbox, I wan't that the combobox gets the first item selected, on the oher hand whenever the user unchecks it, I wan't that the selecteditem of the combobox be null.

How can I accomplish this? I'm following the MVVM pattern, but since this is more a matter of the view, I'm open to code-behind suggestions.


Solution

  • I followed the suggestion provided by @Baboon and I created a custom control with a routed event named CheckedChanged, this way I can access it through the view's xaml and code-behind:

     [TemplatePart(Name = "PART_Expander", Type = typeof(Expander))]
    [TemplatePart(Name = "PART_CheckBox", Type = typeof(CheckBox))]
    public class MyCustomExpander : Expander
    {
        static MyCustomExpander()
        {
            DefaultStyleKeyProperty.OverrideMetadata(typeof(MyCustomExpander), new FrameworkPropertyMetadata(typeof(MyCustomExpander)));
        }
    
        public bool IsChecked
        {
            get { return (bool)GetValue(IsCheckedProperty); }
            set { SetValue(IsCheckedProperty, value); }
        }
        public static readonly DependencyProperty IsCheckedProperty =
            DependencyProperty.Register("IsChecked", typeof(bool), typeof(MyCustomExpander),
                                         new UIPropertyMetadata(false));
    
        #region Events
    
        private CheckBox chkExpander = new CheckBox();
        public CheckBox ChkExpander { get { return chkExpander; } private set { chkExpander = value; } }
    
        public static readonly RoutedEvent CheckedChangedEvent = EventManager.RegisterRoutedEvent("ExtraButtonClick", 
                                                                                                   RoutingStrategy.Bubble, 
                                                                                                   typeof(RoutedEventHandler),
                                                                                                   typeof(MyCustomExpander));
    
        public event RoutedEventHandler CheckedChanged
        {
            add { AddHandler(CheckedChangedEvent, value); }
            remove { RemoveHandler(CheckedChangedEvent, value); }
        }
    
        void OnCheckedChanged(object sender, RoutedEventArgs e)
        {
            RaiseEvent(new RoutedEventArgs(CheckedChangedEvent, this));
        } 
    
        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
    
            CheckBox chk = base.GetTemplateChild("PART_CheckBox") as CheckBox;
            if (chk != null)
            {
                chk.Checked += new RoutedEventHandler(OnCheckedChanged);
                chk.Unchecked += new RoutedEventHandler(OnCheckedChanged);
            }
        }
    
        #endregion
    
    }
    

    I want to thank to @Baboon and @Vlad for their help.