问题
I want to change the margin of the first item in the ListBox if SomeProperty value is 10, without code-behind. This is what I have so far:
<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>
When I try this approach I get:
System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='ListBox', AncestorLevel='1''. BindingExpression:Path=Items.Count; DataItem=null; target element is 'ListBox' (Name=''); target property is 'NoTarget' (type 'Object')
If I have only the first condition, it applies the margin properly. Another way I tried was by using the ElementName:
This approach doesn't give any error but it's not working either.
Any help would be much appreciated.
回答1:
See AlternationIndex. (You can use a very high AlternationCount
to ensure that only the first item has index 0
and trigger on that).
This is a bit abusive, a cleaner method would be a value converter / multi value converter, that gets the index via something like listBox.Items.IndexOf(currentItem)
.
回答2:
Another solution would be subclassing list box, and overriding PrepareContainerForItemOverride method. See my example below (it's for the Silverlight in WP7, so I had no 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;
}
}
Then I derive my items from ListBoxEx.iContainerStyle to get different margins for different items.
来源:https://stackoverflow.com/questions/11462229/styling-a-listboxitem-depending-on-its-index-in-the-listbox