1

对于我的应用程序,我有一个 ItemsControl,其中第一个项目有一个不同的模板(简写为 Template2),其余项目有一个默认模板(Template1)。我已经使用以下 XAML 做到了这一点:

<DataTemplate x:Key="MyDataTemplate">
    <ContentPresenter x:Name="TemplateContentPresenter"
                      Content="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Content}"
                      ContentTemplate="{StaticResource Template1}"/>
    <DataTemplate.Triggers> 
        <DataTrigger Binding="{Binding RelativeSource={RelativeSource Self}, 
     Converter= {StaticResource IsFirstItemInCollectionConverter}}"
                     Value="True">
            <Setter TargetName="TemplateContentPresenter"
                    Property="ContentTemplate"
                    Value="{StaticResource Template2}"/>
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

IsFirstItemInCollectionConverter 的代码如下:

public class IsFirstItemInCollectionConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        DependencyObject item = (DependencyObject)value;
        ItemsControl ic = ItemsControl.ItemsControlFromItemContainer(item);
        Console.WriteLine("converted");
        return (ic.ItemContainerGenerator.IndexFromContainer(item) == 0);
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

问题是当我在 itemsControl 的 itemssource 中进行更改时,我的绑定没有更新。(在显示 itemsControl 的视图中,我有可以添加和删除项目的按钮)。只有在我切换视图并重新加载它之后,绑定才会更新并显示正确的模板。我该如何纠正这种行为?我假设我必须将 UpdateSourceTrigger 设置为显式并手动更新源,但我不知道如何在数据模板中执行此操作。在此先感谢您的帮助。

4

2 回答 2

2

您已经触发了 DataTrigger,Binding="{Binding RelativeSource={RelativeSource Self}当 ListBoxItem 的 datacontext 更改时将触发该 DataTrigger。

我会建议在这里为您的项目控件使用 DataTemplateSelector 并为其设置ItemTemplateSelector属性。在 SelectTemplate 方法中,您可以根据任何逻辑返回新添加项目的模板:

模板选择器:

 public class MyTemplateSelector : DataTemplateSelector
{
    public DataTemplate FirstItemTemplate { get; set; }
    public DataTemplate DefaultItemTemplate { get; set; }

    public override DataTemplate SelectTemplate(object item, DependencyObject container)
    {
        //Logic to return first or default template comes here
    }
}

在xml中:

<local:MyTemplateSelector x:Key="myTemplate">
        <local:MyTemplateSelector.FirstItemTemplate>
            <!--First Template-->
        </local:MyTemplateSelector.FirstItemTemplate>

        <local:MyTemplateSelector.DefaultItemTemplate>
            <!--Default Template-->
        </local:MyTemplateSelector.DefaultItemTemplate>
    </local:MyTemplateSelector>

更新

对于您的特定情况,如果您没有在 itemsControl 中使用交替,您也可以像下面这样解决这个问题。您可以对 ListBox 使用 AlternationCount 并为每个 ListboxItem 绑定到 ItemsControl.AlternationIndex。因此,每当列表框交替索引更改时,您都可以更改其模板:

XAML:

<ListBox AlternationCount="{Binding Items.Count, RelativeSource={RelativeSource Self}}" x:Name="itemControl" ItemsSource="{Binding Items}">
        <ListBox.ItemContainerStyle>
            <Style TargetType="{x:Type ListBoxItem}">
                <Setter Property="Template" Value="{StaticResource DefaultTemplate}" />
                <Style.Triggers>
                    <Trigger Property="ItemsControl.AlternationIndex" Value="0">
                        <Setter Property="Template" Value="{StaticResource FirstTemplate}" />
                    </Trigger>
                </Style.Triggers>
            </Style>
        </ListBox.ItemContainerStyle>
    </ListBox>

这里 DefaultTemplate 和 FirstTemplate 是 controlTemplates。

我试过了,每当我删除索引 0 处的项目时,它都对我有用,它为下一个项目提供了第一个项目模板。

希望对你有效。

谢谢,

于 2013-08-29T02:45:28.143 回答
0

好的,我修复了它,但以一种不雅的方式。我将绑定的项目临时设置为 null 以强制 DataTemplateSelector 每次删除/添加项目时重新评估。

于 2013-09-01T05:43:31.227 回答