需要多种样式依赖于Listboxitem

时间:2013-11-20 08:28:16

标签: wpf listbox styles

我有一个Listbox,它基于相同的基类存储两种不同的对象类型。 (例如,BaseObject = baseclass及其子代:CustomPath和CustomImage)

数据源:

ObservableCollection<BattlegroundBaseObject> _baseObjectCollection;
public ObservableCollection<BattlegroundBaseObject> BaseObjectCollection
{
    get { return _baseObjectCollection?? (_baseObjectCollection= new ObservableCollection<BaseObject>()); }
} 

列表框数据绑定:<ListBox ItemsSource="{Binding BaseObjectCollection}"

<ListBox.ItemContainerStyle>
    <Style TargetType="ListBoxItem" x:Name="ListBoxPathLineStyle">
        <Setter Property="Template">

            <Setter.Value>
                <ControlTemplate TargetType="ListBoxItem" x:Name="BattlegroundObjectControlTemplate">

                    <Path Stroke="{Binding ObjectColor}" StrokeThickness="{Binding StrokeThickness}" Data="{Binding PathGeometryData}" x:Name="PathLine" Opacity="{Binding Opacity}">
                    </Path>
                    <ControlTemplate.Triggers>
                        <Trigger Property="IsSelected" Value="true">
                            <Setter Property="Effect" TargetName="PathLine">
                                <Setter.Value>
                                    <DropShadowEffect Color="CornflowerBlue" ShadowDepth="3" BlurRadius="10" />
                                </Setter.Value>
                            </Setter>
                        </Trigger>
                    </ControlTemplate.Triggers>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>
</ListBox.ItemContainerStyle>

我想添加到Path所在的ControlTemplate,也是一个Image,并根据类型或属性进行区分。没关系。

任何想法?

3 个答案:

答案 0 :(得分:1)

您可以为每种类型添加ListBox资源DataTemplate

在我的示例类CarMotorbike派生自Vehicle类。

<ListBox x:Name="listBox">
    <ListBox.Resources>
        <DataTemplate DataType="{x:Type local:Car}">
            <StackPanel Background="Red">
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </DataTemplate>

        <DataTemplate DataType="{x:Type local:Motorbike}">
            <StackPanel Background="Orange">
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.Resources>
</ListBox>

修改

您可以将ListBoxItem的样式添加到资源:

<ListBox x:Name="listBox">
    <ListBox.Resources>
        <Style TargetType="ListBoxItem">
            <Style.Triggers>
                <Trigger Property="IsSelected" Value="true">
                    <Setter Property="Effect">
                        <Setter.Value>
                            <DropShadowEffect Color="CornflowerBlue" ShadowDepth="3" BlurRadius="10" />
                        </Setter.Value>
                    </Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
        <DataTemplate DataType="{x:Type local:Car}">
            <StackPanel Background="Red">                       
                <TextBlock Text="{Binding Name}" />                        
            </StackPanel>
        </DataTemplate>

        <DataTemplate DataType="{x:Type local:Motorbike}">
            <StackPanel Background="Orange">
                <TextBlock Text="{Binding Name}" />
            </StackPanel>
        </DataTemplate>
    </ListBox.Resources>
</ListBox>

答案 1 :(得分:0)

您可以为不同的类定义一些DataTemplates。它们决定了类的显示方式。在处理基类的集合时,我一直在使用它们以不同的方式显示派生类。

<DataTemplate DataType="{x:Type CustomPath}">
    <TextBlock Text="This is a CustomPath"/>
</DataTemplate>

<DataTemplate DataType="{x:Type CustomImage}">
    <TextBlock Text="This is a CustomImage"/>
</DataTemplate>

答案 2 :(得分:0)

目前,您正在更改WPF用于呈现绑定数据的控件的样式。更好的方法是为WPF提供一种生成正确控件的方法。忽略ListBoxItem并使用DataTemplate s作为实际对象。

首先,你需要告诉窗口或控制如何找到你的类型。

<Window or UserControl
...
    xmlns:model="clr-namespace:yourNamespace"
>

然后,您可以为WPF提供一种显示对象的方法,例如

<DataTemplate TargetType="{x:Type model:CustomPath}">
  <Path Stroke="{Binding ObjectColor}" StrokeThickness="{Binding StrokeThickness}" 
    Data="{Binding PathGeometryData}" x:Name="PathLine" Opacity="{Binding Opacity}"/>
  <!-- maybe use a binding from the Path.Effect back to the IsSelected and ValueConverters 
    to re-apply the selection effect-->
</DataTemplate>

<DataTemplate TargetType="{x:Type model:CustomImage}">
  <Image Src="{Binding SomeProperty}" />
</DataTemplate>

现在您需要做的就是以某种方式使ListBox可用。几乎WPF中的每个元素都可以添加.Resources,因此您可以选择在整个窗口中执行这些操作

<Window ...>
  <Window.Resources>
     <DataTemplate .../>
     <DataTemplate .../>
  </Window.Resources>
  ...
  <ListBox .../>
</Window>

或者您可以在本地更多地应用

<Window ...>
  ...
  <ListBox>
    <ListBox.Resources>
       <DataTemplate .../>
       <DataTemplate .../>
    </ListBox.Resources>
  </ListBox>
</Window>

这样你的列表框定义也可以变得更整洁,例如如果您使用Window.Resources

<ListBox ItemsSource="{Binding BaseObjectCollection}"/>