2010-01-21 37 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> 
相關問題