我在itemscontrol中使用自定义模板来显示以下结果:
item 1, item 2, item3,
我想更改最后一项的模板,结果如下:
item 1, item2, item3
ItemsControl:
<ItemsControl ItemsSource="{Binding Path=MyCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=Name}"/>
<TextBlock Text=", "/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
有没有人可以为我的问题提供解决方案?谢谢!
答案 0 :(得分:53)
我只使用XAML找到了问题的解决方案。如果有人需要这样做,请使用:
<ItemsControl ItemsSource="{Binding Path=MyCollection}">
<ItemsControl.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" IsItemsHost="True"/>
</ItemsPanelTemplate>
</ItemsControl.ItemsPanel>
<ItemsControl.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock x:Name="comma" Text=", "/>
<TextBlock Text="{Binding}"/>
</StackPanel>
<DataTemplate.Triggers>
<DataTrigger Binding="{Binding RelativeSource={RelativeSource PreviousData}}" Value="{x:Null}">
<Setter TargetName="comma" Property="Visibility" Value="Collapsed"/>
</DataTrigger>
</DataTemplate.Triggers>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
答案 1 :(得分:7)
您可以使用DataTemplateSelector,在SelectTemplate()方法中,您可以检查项目是否为最后一项,然后返回其他模板。
在XAML中:
<ItemsControl.ItemTemplate>
<DataTemplate>
<ContentPresenter
ContentTemplateSelector = "{StaticResource MyTemplateSelector}">
在代码背后:
private sealed class MyTemplateSelector: DataTemplateSelector
{
public override DataTemplate SelectTemplate(
object item,
DependencyObject container)
{
// ...
}
}
答案 2 :(得分:2)
此解决方案影响最后一行并更新基础集合:
转换器需要3个参数才能正常运行 - 当前项目,itemscontrol,itemscount,如果当前项目也是最后一项,则返回true:
class LastItemConverter : IMultiValueConverter
{
public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
{
int count = (int)values[2];
if (values != null && values.Length == 3 && count>0)
{
System.Windows.Controls.ItemsControl itemsControl = values[0] as System.Windows.Controls.ItemsControl;
var itemContext = (values[1] as System.Windows.Controls.ContentPresenter).DataContext;
var lastItem = itemsControl.Items[count-1];
return Equals(lastItem, itemContext);
}
return DependencyProperty.UnsetValue;
}
public object[] ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
{
throw new NotImplementedException();
}
}
DataTemplate的数据触发器,其中包含名为&#39; PART_TextBox&#39;的文本框:
<DataTemplate.Triggers>
<DataTrigger Value="True" >
<DataTrigger.Binding>
<MultiBinding Converter="{StaticResource LastItemConverter}">
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}" />
<Binding RelativeSource="{RelativeSource Self}"/>
<Binding RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}" Path="Items.Count"/>
</MultiBinding>
</DataTrigger.Binding>
<Setter Property="Foreground" TargetName="PART_TextBox" Value="Red" />
</DataTrigger>
</DataTemplate.Triggers>
转换器作为Xaml中的静态资源
<Window.Resources>
<local:LastItemConverter x:Key="LastItemConverter" />
</Window.Resources>
它的实际快照
代码已添加到此&#39;代码项目&#39;中的itemscontrol中。 https://www.codeproject.com/Articles/242628/A-Simple-Cross-Button-for-WPF
请注意最后一项红色
的文字答案 3 :(得分:0)
一个问题......我看到你使用的是ItemsControl
,而不是说ListBox
,而且它似乎绑定了一系列字符串,而你只是在尝试显示结果文本而不格式化各个部分,这让我想知道你想要的输出实际上是问题中提到的字符串本身,而不是实际的ItemsControl
本身。
如果我对此是正确的,你是否考虑过只使用一个简单的TextBlock
绑定到items集合,但通过转换器?然后在转换器内部,你将value
转换为一个字符串数组,然后在Convert
方法中,只需Join
使用逗号作为分隔符,它们将自动添加它们元素,像这样......
var strings = (IEnumerable<String>)value;
return String.Join(", ", strings);