2010-01-21 75 views
1

我想装饰一个ItemsControl,以便每个项目都有一个删除按钮,该按钮可以在iPhone UI的某种特定条件下浮动在项目内容上。我有几种方法可以考虑如何处理这个问题,但我可以使用其他WPF人员的一些指导,他们可能对如何最好地完成这个任务有更好的想法。下面是一个模拟图像,以帮助表达我想要做的事情。如何为ItemsControl中的每个项目创建叠加层?

Example mock-up

我现在的想法是尽量只使用XAML在必要时只使用样式,模板,也许附加属性来尝试这一点。这个想法是为项目控件创建条件化的DataTemplate,以某种方式将原始内容用包含我的删除按钮的装饰器包装起来。为了在我的ItemsControl上有一个状态来知道我是否在删除模式或不在,我想创建一个附加属性,然后我可以用各种方法设置它们,例如将它绑定到状态例如切换按钮或复选框。

在这一点上这个概念是有道理的,但细节有点不清楚是否使用ItemTemplate是最好的举动,因为在某些情况下ItemTemplate可能已经存在给定的ItemsControl,我不想覆盖它而是只想包装它(如果有意义的话)。我在想,如果我拉如果关闭权,我应该能够通过指定样式和可能的附加属性将它应用于任何项目控件。

如果有人可以帮助说明这些细节或提供更好的建议,我可以如何去分享。

回答

1

我已经创建了以下模型来说明使用单个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> 

你并不需要太多的代码,使这项工作,但仍有一些隐藏代码,主要用于RoutedCommand

public partial class Foods : Window 
{ 
    private ObservableCollection<String> items = new ObservableCollection<string>(); 
    private RoutedCommand removeItemCommand = new RoutedCommand(); 

    public Foods() 
    { 
     InitializeComponent(); 

     items.Add("Ice Cream"); 
     items.Add("Pizza"); 
     items.Add("Apple"); 

     CommandBindings.Add(new CommandBinding(removeItemCommand, ExecutedRemoveItem)); 
    } 

    public ObservableCollection<String> Items 
    { 
     get { return items; } 
    } 

    public RoutedCommand RemoveItemCommand 
    { 
     get { return removeItemCommand; } 
    } 

    private void ExecutedRemoveItem(object sender, ExecutedRoutedEventArgs e) 
    { 
     DependencyObject container = 
      ItemsControl.ContainerFromElement(e.Source as ItemsControl, e.OriginalSource as DependencyObject); 
     ListBoxItem item = container as ListBoxItem; 
     items.Remove(item.Content as String); 
    } 
} 

而且结果可以作出很明显,在视觉上很吸引人,但我几乎复制了你的想法哈哈:

alt text http://img697.imageshack.us/img697/7033/foodswindow.png

2

通常情况下,您可以在ItemContainerStyle中添加这样的内容,以免每次需要应用DataTemplate本身。虽然这对ListBox来说很简单,您可以在其中修改ListBoxItem的模板,但不幸的是,基础ItemsControl仅使用ContentPresenter作为其容器,因此无法以相同的方式进行模板化。

如果你真的希望这是可重用的,我建议你将它包装到一个新的自定义ItemsControl中,您可以放入其中以替换标准的一个,而无需修改正在使用的特定DataTemplate。这也可以让你包装属性,否则你将在外部创建属性作为附属的道具和控制本身的删除命令。

显然,删除逻辑和视觉造型还没有在这里做,但这应该让你开始:

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> 
相关问题