Convention binds to child button in ControlTemplate (bug?)

Topics: Bugs, Conventions
Jan 11, 2013 at 7:03 PM


I run into the following issue today and I am wondering if this is a bug or if I missed something.

I implemented a SplitButton control:

    [TemplatePart(Name = "PART_MainButton", Type = typeof(Button))]
    [TemplatePart(Name = "PART_DropDownButton", Type = typeof(ToggleButton))]
    public class SplitButton : ButtonBase

I map the MainButton_Click to the control's Click event:

            var mainButton = GetMainButton();
            if (mainButton != null)
                mainButton.Click += mainButton_Click;

... and ...

        void mainButton_Click(object sender, RoutedEventArgs e)

The ControlTemplate looks like this:

    <Style TargetType="{x:Type tsc:SplitButton}">
        <Setter Property="Template">
                <ControlTemplate TargetType="{x:Type tsc:SplitButton}">
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="Auto"/>
                        <Button Name="PART_MainButton"  Grid.Column="0">
                            <ContentPresenter Content="{TemplateBinding Content}" />
                        <ToggleButton Name="PART_DropDownButton" Grid.Column="1" Padding="3">
                            <Path Name="dropDownArrow" Fill="{DynamicResource DropDownArrowBrushSelected}" Data="M 0 0 L 4 4 L 8 0 Z"  Height="5" Margin="0"/>

Ok, so far it works.

Now I use my control in a View:

                        <local:SplitButton Name="ExportTest" Content="Export">

and declare a method in my ViewModel:

        public void ExportTest()
            var t = "Test";

The problem is that the ExportTest() method is called twice when I click on the MainButton and once when I click on the DropDownButton. In the first case it should only be called once and in the second case it should not be called at all.

Further tests revealed that Caliburn.Micro is binding the ExportTest() method to the two buttons within the ControlTemplate. Very strange.... Even if CM applied conventions to the controls within the ControlTemplate - and I am not sure if it should or should not do it - the buttons within the ControlTemplate have Names as well and I do not understand why they are bound to a method with their parent's name?

Any idea?

BTW, thanks for the great framework! - I used Microsoft Prism before, than Prism with Caliburn.Micro together and then switched to Caliburn.Micro all together and I am not looking back. I am happy that Caliburn.Micro is maintained and has a great future where as Prism seems like a dead end.

Best regards,




Jan 14, 2013 at 1:14 PM
Edited Jan 14, 2013 at 1:15 PM


I found the cause and the solution.

I was wrong - CM does not bind to the child buttons.

The Click RoutedEvent is passed to the parent and handled there by CM.

The solution is to set e.Handled in the control's code:


        void mainButton_Click(object sender, RoutedEventArgs e)
            e.Handled = true;


Still I am not sure if CM should call an Action if the Click event originated from a child from within the ControlTemplate. Maybe CM should check if the Source of the Click event is really the element to which the Action was attached?