具有模板命令绑定的自定义 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}"/>
我尝试构建自定义 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}"/>