Exception occurs when button clicked inside my custom control

纵然是瞬间 提交于 2019-12-10 23:27:31

问题


I have made a UWP custom templated control that contains a collection of ICommandBarElement, much like the standard CommandBar control. The problem is that as soon as I click on any of the AppBarButton contained in my CommandBar implementation, an unhandled exception occurs: "No such interface supported".

There is something I must doing wrong but I just can't see it. Here is the code for the custom control:

public sealed class MyCommandBarControl : ContentControl
{
    public MyCommandBarControl()
    {
        this.DefaultStyleKey = typeof(MyCommandBarControl);

        this.PrimaryCommands = new ObservableCollection<ICommandBarElement>();
    }

    public ObservableCollection<ICommandBarElement> PrimaryCommands
    {
        get { return (ObservableCollection<ICommandBarElement>)GetValue(PrimaryCommandsProperty); }
        set { SetValue(PrimaryCommandsProperty, value); }
    }

    /// <summary>
    /// PrimaryCommands Dependency Property
    /// </summary>
    public static readonly DependencyProperty PrimaryCommandsProperty =
        DependencyProperty.Register(
            "PrimaryCommands",
            typeof(ObservableCollection<ICommandBarElement>),
            typeof(MainPage),
            new PropertyMetadata(null, null));


    protected override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        var primaryItemsControl = GetTemplateChild("PrimaryItemsControl") as ItemsControl;
        primaryItemsControl.ItemsSource = this.PrimaryCommands;

    }

}

And the associated Style:

<Style TargetType="local:MyCommandBarControl" >
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:MyCommandBarControl">
                <Grid x:Name="LayoutRoot" Background="{TemplateBinding Background}">
                    <Grid x:Name="ContentRoot"
                          VerticalAlignment="{TemplateBinding VerticalAlignment}"
                          Margin="{TemplateBinding Padding}"
                          Height="{TemplateBinding Height}"
                          Background="{TemplateBinding Background}"
                          Opacity="{TemplateBinding Opacity}">

                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                        </Grid.ColumnDefinitions>

                        <ContentControl
                              x:Name="ContentControl"
                              Content="{TemplateBinding Content}"
                              ContentTemplate="{TemplateBinding ContentTemplate}"
                              ContentTransitions="{TemplateBinding ContentTransitions}"
                              Foreground="{TemplateBinding Foreground}"
                              HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                              VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                              HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}"
                              VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"
                             IsTabStop="False"
                             Margin="10, 0, 0, 0"/>

                        <ItemsControl 
                              x:Name="PrimaryItemsControl"
                              IsTabStop="False"
                              Grid.Column="1"
                              Margin="10, 0, 0, 0"
                              HorizontalAlignment="Right"  
                              HorizontalContentAlignment="Right">
                            <ItemsControl.ItemsPanel>
                                <ItemsPanelTemplate>
                                    <StackPanel Orientation="Horizontal" />
                                </ItemsPanelTemplate>
                            </ItemsControl.ItemsPanel>
                        </ItemsControl>
                    </Grid>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

I have made a small project you can download that reproduces the problem. Any help resolving this exception would be appreciated.


回答1:


Why not inherit from CommandBar control, and don't need to manage the PrimaryCommands by ourselves.

So simply change your code to the following can solve the issue:

public sealed class MyCommandBarControl : CommandBar
{
    public MyCommandBarControl()
    {
        this.DefaultStyleKey = typeof(MyCommandBarControl);

        //this.PrimaryCommands = new ObservableCollection<ICommandBarElement>();
    }

    //public ObservableCollection<ICommandBarElement> PrimaryCommands
    //{
    //    get { return (ObservableCollection<ICommandBarElement>)GetValue(PrimaryCommandsProperty); }
    //    set { SetValue(PrimaryCommandsProperty, value); }
    //}

    ///// <summary>
    ///// PrimaryCommands Dependency Property
    ///// </summary>
    //public static readonly DependencyProperty PrimaryCommandsProperty =
    //    DependencyProperty.Register(
    //        "PrimaryCommands",
    //        typeof(ObservableCollection<ICommandBarElement>),
    //        typeof(MainPage),
    //        new PropertyMetadata(null, null));


    protected override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        var primaryItemsControl = GetTemplateChild("PrimaryItemsControl") as ItemsControl;
        primaryItemsControl.ItemsSource = this.PrimaryCommands;

    }

}

[Update1]

I think there is underlying type conversion we cannot see or we have to use some interfaces like ICommandBar but we cannot use due to its protection level.

If you do hope to implement CommandBar by yourself, I think it's better to create your own Command button instead of using AppBarButton. But you need to make sure you have a solid reason to do it by yourself.

For example, the following will work if I use a default Button.

public sealed class MyCommandBarControl : ContentControl
{
    public MyCommandBarControl()
    {
        this.DefaultStyleKey = typeof(MyCommandBarControl);

        this.PrimaryCommands = new ObservableCollection<Button>();
    }

    public ObservableCollection<Button> PrimaryCommands
    {
        get { return (ObservableCollection<Button>)GetValue(PrimaryCommandsProperty); }
        set { SetValue(PrimaryCommandsProperty, value); }
    }

    /// <summary>
    /// PrimaryCommands Dependency Property
    /// </summary>
    public static readonly DependencyProperty PrimaryCommandsProperty =
        DependencyProperty.Register(
            "PrimaryCommands",
            typeof(ObservableCollection<Button>),
            typeof(MainPage),
            new PropertyMetadata(null, null));


    protected override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        var primaryItemsControl = GetTemplateChild("PrimaryItemsControl") as ItemsControl;
        primaryItemsControl.ItemsSource = this.PrimaryCommands;

    }

}

In MainPage.xaml

    <local:MyCommandBarControl>
        <local:MyCommandBarControl.Content>
            <TextBlock Text="My CommandBar" />
        </local:MyCommandBarControl.Content>

        <local:MyCommandBarControl.PrimaryCommands>
            <Button Content="Pin" Click="PinBarButton_Click" />
            <Button Content="UnPin" />
            <Button Content="Sync"  />
            <Button Content="Remove" />
        </local:MyCommandBarControl.PrimaryCommands>
    </local:MyCommandBarControl>


来源:https://stackoverflow.com/questions/33508244/exception-occurs-when-button-clicked-inside-my-custom-control

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!