Wpf 如何为ItemsControl中的每个项创建覆盖?
我试图装饰一个ItemsControl,这样每个项目都会有一个Delete按钮,在特定条件下浮动在项目的内容上,这在某种程度上是受iPhone UI启发的。我有一些方法可以解决这个问题,但我可以从其他WPF人员那里得到一些指导,他们可能对如何最好地解决这个问题有更好的想法。下面是一个模型图片,以帮助表达我试图做什么 我目前的想法是尝试只使用XAML,只使用样式、模板,必要时还可以使用附加属性。其思想是为items控件创建条件DataTemplate,该控件将以某种方式使用包含“我的删除”按钮的装饰器包装原始内容。为了在我的ItemsControl上有一个状态,以便知道我是否处于删除模式,我想也许可以创建一个附加属性,然后通过多种方式进行设置,例如将其绑定到切换按钮或复选框的状态 在这一点上,这个概念是有意义的,但是细节对我来说有点不清楚使用ItemTemplate是否是最好的方法,因为在某些情况下,对于给定的ItemsControl,ItemTemplate可能已经存在,我不想覆盖它,而是只想包装它(如果有意义的话)。我在想,如果我正确地选择if,我应该能够通过指定样式和可能附加的属性将其应用于任何items控件Wpf 如何为ItemsControl中的每个项创建覆盖?,wpf,xaml,overlay,itemscontrol,adorner,Wpf,Xaml,Overlay,Itemscontrol,Adorner,我试图装饰一个ItemsControl,这样每个项目都会有一个Delete按钮,在特定条件下浮动在项目的内容上,这在某种程度上是受iPhone UI启发的。我有一些方法可以解决这个问题,但我可以从其他WPF人员那里得到一些指导,他们可能对如何最好地解决这个问题有更好的想法。下面是一个模型图片,以帮助表达我试图做什么 我目前的想法是尝试只使用XAML,只使用样式、模板,必要时还可以使用附加属性。其思想是为items控件创建条件DataTemplate,该控件将以某种方式使用包含“我的删除”按钮的
如果有人能帮助说明这些更详细的细节,或者就如何进行提供更好的建议,请与我们分享。我创建了以下模型,以说明一种简单的方法,即使用一个
数据模板
几个绑定。你肯定是在正确的轨道上
<Window x:Class="TestWpfApplication.Foods"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:TestWpfApplication"
xmlns:sys="clr-namespace:System;assembly=mscorlib"
Title="Foods" ResizeMode="NoResize"
SizeToContent="WidthAndHeight"
DataContext="{Binding RelativeSource={RelativeSource Self}}">
<Window.Resources>
<local:BoolToVisConverter x:Key="BoolToVisConverter"/>
</Window.Resources>
<StackPanel Background="LightGray">
<ToggleButton Name="EditModeToggle" Content="Edit" HorizontalAlignment="Right" FontFamily="Arial" Padding="4"
Background="#7FA4E6" Foreground="White" BorderBrush="Black" Width="60" Margin="5,5,5,0"/>
<ListBox ItemsSource="{Binding Items}"
Background="#999" BorderBrush="Black" Margin="5">
<ListBox.ItemTemplate>
<DataTemplate>
<Border CornerRadius="8" Background="#3565BC" Padding="8"
BorderBrush="#333" BorderThickness="1" Margin="2" Width="255">
<StackPanel Orientation="Horizontal">
<Button Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Path=RemoveItemCommand}"
Visibility="{Binding ElementName=EditModeToggle, Path=IsChecked, Converter={StaticResource BoolToVisConverter}}">
<Button.Content>
<TextBlock Foreground="Red" Text="X" FontWeight="Bold"/>
</Button.Content>
</Button>
<TextBlock Text="{Binding}" Margin="12,0" Foreground="#AAA" VerticalAlignment="Center"
FontSize="14" FontWeight="Bold" FontFamily="Arial"/>
</StackPanel>
</Border>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
很明显,结果在视觉上更具吸引力,但我几乎复制了你的想法哈哈:
通常情况下,您会在ItemContainerStyle中添加类似的内容,以免每次应用时都弄乱数据模板本身。虽然这对于ListBox来说很简单,您可以在其中修改ListBoxItem的模板,但不幸的是,基本ItemsControl仅使用ContentPresenter作为其容器,因此不能以相同的方式进行模板化 如果你真的希望它是可重用的,我建议你将它包装成一个新的自定义ItemsControl,你可以访问它来替换一个标准控件,而不必修改正在使用的特定DataTemplate。这还将允许您将原本在外部创建的属性包装为附加的道具,并在控件本身中使用delete命令 显然,这里没有完成删除逻辑和视觉样式,但这应该可以让您开始:
public class DeleteItemsControl : ItemsControl
{
public static readonly DependencyProperty CanDeleteProperty = DependencyProperty.Register(
"CanDelete",
typeof(bool),
typeof(DeleteItemsControl),
new UIPropertyMetadata(null));
public bool CanDelete
{
get { return (bool)GetValue(CanDeleteProperty); }
set { SetValue(CanDeleteProperty, value); }
}
public static RoutedCommand DeleteCommand { get; private set; }
static DeleteItemsControl()
{
DeleteCommand = new RoutedCommand("DeleteCommand", typeof(DeleteItemsControl));
DefaultStyleKeyProperty.OverrideMetadata(typeof(DeleteItemsControl), new FrameworkPropertyMetadata(typeof(DeleteItemsControl)));
}
protected override DependencyObject GetContainerForItemOverride()
{
return new DeleteItem();
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is DeleteItem;
}
}
public class DeleteItem : ContentControl
{
static DeleteItem()
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(DeleteItem), new FrameworkPropertyMetadata(typeof(DeleteItem)));
}
}
这将放在Generic.xaml中,或者您可以像在应用程序中应用普通样式一样应用它们:
<Style TargetType="{x:Type local:DeleteItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:DeleteItemsControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ItemsPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:DeleteItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:DeleteItem}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<DockPanel>
<Button Command="local:DeleteItemsControl.DeleteCommand" Content="X" HorizontalAlignment="Left" VerticalAlignment="Center"
Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:DeleteItemsControl}}, Path=CanDelete, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:DeleteItemsControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:DeleteItemsControl}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ItemsPresenter/>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="{x:Type local:DeleteItem}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:DeleteItem}">
<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<DockPanel>
<Button Command="local:DeleteItemsControl.DeleteCommand" Content="X" HorizontalAlignment="Left" VerticalAlignment="Center"
Visibility="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:DeleteItemsControl}}, Path=CanDelete, Converter={StaticResource BooleanToVisibilityConverter}}"/>
<ContentPresenter VerticalAlignment="{TemplateBinding VerticalContentAlignment}" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"/>
</DockPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>