【问题标题】:Explicitly refresh DataTemplate from a DataTemplateSelector?从 DataTemplateSelector 显式刷新 DataTemplate?
【发布时间】:2011-01-06 07:51:30
【问题描述】:

我将 ContentControl.DataTemplateSelector 设置为我想要的。
我希望根据命令或其他方式调用 ContentControl 以通过 xaml 或代码从选择器中重新选择模板。

谢谢

【问题讨论】:

    标签: wpf xaml datatemplate contentcontrol datatemplateselector


    【解决方案1】:

    聚会迟到了,我知道。 =)

    当遇到这个问题时,我发现像这样显式设置一个新的 TemplateSelector 是最简单的

    MyContentControl.ContentTemplateSelector =
         new MyDataTemplateSelector();
    

    【讨论】:

    • +1 永远不会太晚!不像其他令人沮丧的帖子,因为它们告诉你没有办法做你想做的事!你的解决方案有效,给了我一个好主意,我会在今天有时间的时候发布它。
    • 我实际上所做的是将调用 SelectTemplate(作为弱引用)的每个演示者存储在我的 DataTemplateSelector 中,并提供一个静态方法来刷新所有这些。
    • 如果您在绑定的属性上引发属性更改事件会发生什么(如果您绑定到自己的类)?
    • 如果内容的类型没有改变,我相信它是使用当前模板渲染的,而不是再次询问模板选择器。
    • 这会使组件再次完全重新渲染,即使选择的模板相同:/
    【解决方案2】:

    我想我参加派对的时间更晚了,但是为了一个可能对某人有所帮助的不同想法......

    您也可以尝试在ContentControls ContentTemplate 属性上使用ValueConverter,而不是DataTemplateSelector

    只需在 DataContext 中有一个属性即可绑定,例如 ScreenNumber。然后在ValueConverter 中返回与ScreenNumber 关联的DataTemplate

    示例值转换器:

    public class ValueDataTemplateConverter : IValueConverter
    {
        public DataTemplate TemplateA { get; set; }
        public DataTemplate TemplateB { get; set; }
    
        public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
        {
            if (value is ValueType valueType)
                switch (valueType)
                {
                    case ValueType.TypeA:
                        return TemplateA;
                    case ValueType.TypeB:
                        return TemplateB;
                 }
    
            return null;
        }
    
        public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
        {
            throw new NotImplementedException();
        }
    }
    

    示例 xaml 资源:

    <converters:ValueDataTemplateConverter x:Key="ValueDataTemplateConverter">
        <converters:ValueDataTemplateConverter.TemplateA>
            <DataTemplate>
                <TextBox Text="{Binding Value}" />
            </DataTemplate>
        </converters:ValueDataTemplateConverter.TemplateA>
        <converters:ValueDataTemplateConverter.TemplateB>
            <DataTemplate>
                <CheckBox IsChecked="{Binding Value}" />
            </DataTemplate>
        </converters:ValueDataTemplateConverter.TemplateB>
    </converters:ValueDataTemplateConverter>
    

    【讨论】:

    • 感谢您多年后的更新。我不会想到使用转换器,而且这个解决方案不需要代码隐藏。非常好。
    【解决方案3】:

    我不知道有任何(非笨拙的)方法可以做到这一点:当 WPF 需要选择模板时调用 DataTemplateSelector,就 WPF 而言,这是一次性决定。 (您可以通过让 WPF 认为内容已更改来混淆它,例如通过将内容设置为 null 然后再返回 - 我认为这可行但尚未对其进行测试 - 但这很丑陋!)如果有一个很好的方法,我也很想知道!

    但是,还有另一种方法可以更改内容的显示方式, 会根据数据更改进行更新,即通过触发器。您可以使用 DataTemplate.Triggers 集合中的 DataTriggers 来根据内容数据显示和隐藏元素。要更改整个显示,您可以例如在一个 Grid 中设置两个渲染,并使用触发器来控制哪个是可见的。您甚至可以将数据模板设为 ContentControl,并使用触发器来更改 ContentTemplate。当然,这取决于将模板更改为可绑定属性的标准,但情况可能并非总是如此。

    Here's some brief discussion of selectors vs. triggers,尽管上下文略有不同。

    【讨论】:

    【解决方案4】:

    类似于 Jens 的回答,您可以使用 DataTemplateSelector 的现有实例,而不是创建新实例。

    var currentSelector = MyContentControl.ContentTemplateSelector;     
    MyContentControl.ContentTemplateSelector = null;
    MyContentControl.ContentTemplateSelector = currentSelector;
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-02-14
      • 1970-01-01
      • 1970-01-01
      • 2010-12-19
      • 1970-01-01
      • 1970-01-01
      • 2017-09-10
      相关资源
      最近更新 更多