【问题标题】:Force Update of RelativeSource Binding in WPF在 WPF 中强制更新 RelativeSource 绑定
【发布时间】:2013-09-01 04:39:29
【问题描述】:

对于我的应用程序,我有一个 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 设置为显式并手动更新源,但我不知道如何在数据模板中执行此操作。提前感谢您的帮助。

【问题讨论】:

    标签: wpf binding datatemplate observablecollection itemscontrol


    【解决方案1】:

    您已在Binding="{Binding RelativeSource={RelativeSource Self} 上触发了 DataTrigger,它将在 ListBoxItem 的数据上下文更改时触发。

    我会建议在这里为您的项目控件使用 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
        }
    }
    

    在 xaml 中:

    <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 处的项目时,它都对我有用,它会为下一个项目提供第一个项目模板。

    希望它对你有用。

    谢谢,

    【讨论】:

    • 您好,感谢您的回复。我使用了您描述的方法,但出现了同样的问题;删除 ItemsControl 绑定到的 ObservableCollection 的索引 0 后,模板不会立即更新。我需要在更新应用之前切换视图。您还有其他想法吗?
    【解决方案2】:

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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-06-28
      • 1970-01-01
      • 1970-01-01
      • 2017-03-22
      相关资源
      最近更新 更多