在我的自定义控件中单击按钮时发生异常

时间:2015-11-03 20:15:51

标签: xaml uwp

我制作了一个UWP自定义模板控件,其中包含一个ICommandBarElement集合,非常类似于标准的CommandBar控件。问题是,只要我单击CommandBar实现中包含的任何AppBarButton,就会发生未处理的异常:“不支持此类接口”。

有些事情我必须做错,但我看不到它。以下是自定义控件的代码:

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;

    }

}

以及相关的风格:

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

我制作了一个small project you can download来重现问题。任何有助于解决此异常的帮助都将受到赞赏。

1 个答案:

答案 0 :(得分:1)

为什么不从CommandBar控件继承,也不需要自己管理PrimaryCommands。

因此,只需将代码更改为以下内容即可解决问题:

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]

我认为存在我们看不到的基础类型转换,或者我们必须使用某些接口,例如ICommandBar,但由于其保护级别,我们无法使用。

如果您希望自己实现CommandBar,我认为创建自己的Command按钮而不是使用AppBarButton会更好。 但是你需要确保你有充分的理由自己做。

例如,如果我使用默认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;

    }

}

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