根据ListBox中的索引设置ListBoxItem的样式

时间:2012-07-12 23:35:54

标签: wpf xaml listbox listboxitem multidatatrigger

如果SomeProperty值为10,我想更改ListBox中第一项的边距,没有代码隐藏。 这就是我到目前为止所做的:

<ListBox  x:Class="Windows.CustomList"
                 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
                 xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
                 xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
                 xmlns:local="clr-namespace:Windows"
                 mc:Ignorable="d" x:Name="MyList"
                 d:DesignHeight="300" d:DesignWidth="300">
    <ListBox.ItemContainerStyle>
        <Style TargetType="{x:Type ListBoxItem}">
            <Style.Triggers>
                <MultiDataTrigger>
                    <MultiDataTrigger.Conditions>
                        <Condition Binding="{Binding Path=SomeProperty}" Value="10"/>
                        <Condition Binding="{Binding Path=Items.Count, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type ListBox}}}" Value="1" />
                    </MultiDataTrigger.Conditions>
                    <Setter Property="Margin">
                        <Setter.Value>
                            <Thickness Left="500"/>
                        </Setter.Value>
                    </Setter>
                </MultiDataTrigger>
            </Style.Triggers>
        </Style>
    </ListBox.ItemContainerStyle>
    <ListBox.ItemTemplate>
        <DataTemplate>
            <local:ListBoxItemCustomTemplate/>
        </DataTemplate>
    </ListBox.ItemTemplate>
    <ListBox.ItemsPanel>
        <ItemsPanelTemplate>
            <WrapPanel Orientation="Horizontal"/>
        </ItemsPanelTemplate>
    </ListBox.ItemsPanel>
</ListBox>

当我尝试这种方法时,我得到:

  

System.Windows.Data错误:4:无法找到绑定源,引用'RelativeSource FindAncestor,AncestorType ='ListBox',AncestorLevel ='1''。 BindingExpression:路径= Items.Count;的DataItem = NULL; target元素是'ListBox'(Name =''); target属性是'NoTarget'(类型'Object')

如果我只有第一个条件,它会正确应用保证金。 我尝试的另一种方法是使用ElementName:

这种方法不会产生任何错误,但它也不起作用。

非常感谢任何帮助。

2 个答案:

答案 0 :(得分:4)

AlternationIndex。 (您可以使用非常高的AlternationCount来确保只有第一个项目具有索引0并触发该项目。“

这有点滥用,更简洁的方法是值转换器/多值转换器,它通过类似listBox.Items.IndexOf(currentItem)的方式获取索引。

答案 1 :(得分:0)

另一个解决方案是子类化列表框,并覆盖PrepareContainerForItemOverride方法。请参阅下面的示例(这是WP7中的Silverlight,所以我没有AlternationIndex)..

public class ListBoxEx: ListBox
{
    public interface iContainerStyle
    {
        Thickness containerMargin { get; }
        Thickness containerPadding { get; }
    };

    protected override void PrepareContainerForItemOverride( DependencyObject element, Object item )
    {
        base.PrepareContainerForItemOverride( element, item );

        var style = item as iContainerStyle;
        if( null == style )
            return;

        var container = element as ListBoxItem;
        if( null == container )
            return;
        container.Margin = style.containerMargin;
        container.Padding = style.containerPadding;
    }
}

然后我从ListBoxEx.iContainerStyle派生我的项目,以获得不同项目的不同边距。