2013-08-28 60 views
1

对于我的应用程序,我有一个ItemsControl,它具有用于第一项的独特模板(简称为Template2)和其余项目的默认模板(Template1)。我曾与下面的XAML这样做:强制更新WPF中的RelativeSource绑定

<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设置为显式并手动更新源,但我不知道如何在数据模板内部执行此操作。先谢谢您的帮助。

回答

2

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

我会在这里建议使用DataTemplateSelector来进行物品控制,并设置ItemTemplateSelector属性。在SelectTemplate方法,你可以为新添加的项目返回模板依赖于任何逻辑:

TemplateSelector:

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 
    } 
} 

在XAML:

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

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

UPDATE

为您的特定如果你没有在你的itemsControl中使用替换,你可以像下面这样解决这个问题。你可以使用AlternationCount给你ListBox并绑定到每个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的项目时,它都会为我工作,它会给出下一个项目的第一个项目模板。

希望它适合你。

谢谢,

+0

你好,谢谢你的回复。我使用了你描述的方法,但同样的问题发生了;当我删除I​​temControl绑定的ObservableCollection的索引0时,模板不会立即更新。在更新应用之前,我需要切换视图。你还有其他建议吗? –

+0

@ClementHoang为你做了更新的答案吗? – Nitin

0

好吧,我固定它,但在一个不雅的态度。每次删除/添加项目时,我都会将绑定项目临时设置为null以强制DataTemplateSelector进行重新评估。

+0

请看我的回答更新是否对你有帮助。谢谢 – Nitin