具有模板命令绑定的自定义 ListboxItem

Custom ListboxItem with Template Command Binding

我尝试构建自定义 ListboxItem,但我很难将命令绑定到我的 TemplateControl。

<Style x:Key="{x:Type controls:NavigationRailItem}" TargetType="{x:Type controls:NavigationRailItem}">
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="BorderThickness" Value="0"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type controls:NavigationRailItem}" >
                <StackPanel Orientation="Vertical" >
                    <StackPanel.InputBindings>
                        <MouseBinding Gesture="LeftClick" Command="{TemplateBinding Command}"/>
                    </StackPanel.InputBindings>
                    <materialDesign:PackIcon Kind="{TemplateBinding IconKind}"  HorizontalAlignment="Stretch" Width="25" Height="25" VerticalAlignment="Stretch"/>
                    <TextBlock Text="{TemplateBinding Text}" FontSize="11" HorizontalAlignment="Center"/>
                    <ContentPresenter/>
                </StackPanel>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>
public class NavigationRailItem : ListBoxItem
{
    static NavigationRailItem()
    {
        DefaultStyleKeyProperty.OverrideMetadata(typeof(NavigationRailItem), new FrameworkPropertyMetadata(typeof(NavigationRailItem)));
    }

    public PackIconKind IconKind
    {
        get { return (PackIconKind)GetValue(IconKindProperty); }
        set { SetValue(IconKindProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty IconKindProperty =
        DependencyProperty.Register(nameof(IconKind), typeof(PackIconKind), typeof(NavigationRailItem), new PropertyMetadata(default(PackIconKind)));

    public string Text
    {
        get { return (string)GetValue(TextProperty); }
        set { SetValue(TextProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Text.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty TextProperty =
        DependencyProperty.Register(nameof(Text), typeof(string), typeof(NavigationRailItem), new PropertyMetadata(""));

    public ICommand Command
    {
        get { return (ICommand)GetValue(CommandProperty); }
        set { SetValue(CommandProperty, value); }
    }

    // Using a DependencyProperty as the backing store for Command.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty CommandProperty =
        DependencyProperty.Register(nameof(Command), typeof(ICommand), typeof(NavigationRailItem), 
            new PropertyMetadata(default(ICommand)));
}

在我的 MainWindow 中,我尝试将命令绑定到我的 ViewModel。如果我尝试直接绑定我的 DependencyProperty,我不会收到 Click 事件。 如果我再次使用 InputBinding 在 MainWindow 中绑定它,我就会得到它。最后测试的是直接使用ListboxItem的原生实现

<ListBox Grid.Column="1" HorizontalAlignment="Center">
    <Controls1:NavigationRailItem IconKind="Car" Text="Test1" Command="{Binding TestCommand}"/>
    <Separator Height="10"/>
    <Controls1:NavigationRailItem IconKind="XboxLive" Text="Test2" >
        <Controls1:NavigationRailItem.InputBindings>
            <MouseBinding Gesture="LeftClick" Command="{Binding TestCommand}"/>
        </Controls1:NavigationRailItem.InputBindings>
    </Controls1:NavigationRailItem>
    <ListBoxItem >
        <StackPanel Orientation="Vertical" >
            <StackPanel.InputBindings>
                <MouseBinding Gesture="LeftClick" Command="{Binding TestCommand}"/>
            </StackPanel.InputBindings>
            <materialDesign:PackIcon Kind="Apple"  HorizontalAlignment="Stretch" Width="25" Height="25" VerticalAlignment="Stretch"/>
            <TextBlock Text="Test3" FontSize="11" HorizontalAlignment="Center"/>
        </StackPanel>
    </ListBoxItem>
</ListBox>

谁能告诉我我做错了什么?我想了解如何构建自己的控件。

TemplateBinding 只能在 ControlTemplate 内使用。因此,要解决此问题,请在您的控件模板中更改此行:

<MouseBinding Gesture="LeftClick" Command="{TemplateBinding Command}"/>

对此:

<MouseBinding Gesture="LeftClick" Command="{Binding RelativeSource={RelativeSource Mode=TemplatedParent}, Path=Command}"/>