【问题标题】:Behavior Initialisation in Datatemplates数据模板中的行为初始化
【发布时间】:2013-08-19 09:13:28
【问题描述】:

我知道数据模板中的附加属性会发生有趣的事情,但这很奇怪。

我有一个带有依赖属性的行为,属性类型为List<DataStatePair>

[System.Windows.Markup.ContentProperty("StateDefinitions")]
public class MultiDataStateBehavior: StateBehaviourBase
{
    public List<DataStatePair> StateDefinitions
    {
        get { return (List<DataStatePair>)GetValue(StateDefinitionsProperty); }
        set { SetValue(StateDefinitionsProperty, value); }
    }

    // Using a DependencyProperty as the backing store for StateDefinitions.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty StateDefinitionsProperty =
        DependencyProperty.Register("StateDefinitions", typeof(List<DataStatePair>), typeof(MultiDataStateBehavior), new PropertyMetadata(new List<DataStatePair>()));
}

如您所见,我已将其标记为内容属性。 XAML 如下所示:

<DataTemplate>
<!-- VISUAL STATES  OMITTED FOR BREVITY-->
<Grid x:Name="grid" Background="Transparent" ContextMenu="{StaticResource ContextMenu_ToolMenu}">
                    <i:Interaction.Behaviors>
                        <ext:MultiDataStateBehavior Binding="{Binding Type}">
                                <ext:DataStatePair State="None" Value="{x:Null}"/>
                                <ext:DataStatePair State="Gauge" Value="{x:Static jcm:ToolType.Gauge}"/>
                                <ext:DataStatePair State="Repeater" Value="{x:Static jcm:ToolType.Gauge}"/>
                        </ext:MultiDataStateBehavior>
                    </i:Interaction.Behaviors>
</Grid>
</DataTemplate>

问题?每次使用数据模板都会添加 3 个 DataStatePair 实例。我在我的应用程序中使用了该模板 32 次,总共获得了 96 个 DataStatePair 实例。灰熊!我明白这怎么可能。行为对于数据模板是静态的,但 DataStatePair 实例不是静态的,可以添加一个列表。

如果将依赖属性更改为 IEnumerable,一切都会中断 - 它不会编译。如果我在 XAML 中使用 x:Array 显式设置属性,一切都会按预期工作 - 我只得到 3 个状态。 XAML 下面;

<i:Interaction.Behaviors>
                        <ext:MultiDataStateBehavior Binding="{Binding Type}" UseTransitionsOnLoad="True">
                            <ext:MultiDataStateBehavior.StateDefinitions>
                                <x:Array Type="{x:Type ext:DataStatePair}">
                                    <ext:DataStatePair State="None" Value="{x:Null}"/>
                                    <ext:DataStatePair State="Gauge" Value="{x:Static jcm:ToolType.Gauge}"/>
                                    <ext:DataStatePair State="Repeater" Value="{x:Static jcm:ToolType.Gauge}"/>
                                </x:Array>
                            </ext:MultiDataStateBehavior.StateDefinitions>
                        </ext:MultiDataStateBehavior>
</i:Interaction.Behaviors>

有谁知道这是为什么以及最优雅的解决方案是什么。我可以想象微软的实现不会让你使用 x:Array。

编辑:x:Array 解决方案破坏了混合设计器。

XamlParseException:向类型集合添加值 'System.Collections.Generic.IEnumerable(SSW.WPFExtensions.DataStatePair)' 抛出异常。

编辑:删除[System.Windows.Markup.ContentProperty("StateDefinitions")] 属性定义效果很好。我不明白这是怎么回事!

WPF,你在做什么。 WPF、STAHP

【问题讨论】:

    标签: wpf datatemplate attachedbehaviors


    【解决方案1】:

    潜在的解决方案……这太棒了。

    Microsoft 提供了有关创建作为集合的依赖项属性的指南 here.

    本文档规定您永远不应将属性的默认值声明为实例,而是在所属类的构造函数中初始化集合并设置依赖属性。例如。

    public Aquarium() : base()
    {
        SetValue(AquariumContentsPropertyKey, new List<FrameworkElement>()); 
    }
    

    ...[the] 单个列表默认值 Aquarium 的所有实例共享值。如果你运行 以下测试代码,旨在显示您将如何 实例化两个单独的 Aquarium 实例并添加一个不同的 对他们每个人钓鱼,你会看到一个令人惊讶的结果:

    至于我的设计时例外。新的DataStatePair[0] 会出现同样的问题,它是不可变的,可怕的错误报告。

    结论 - 微软的某个人正在以我为代价大笑。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2020-11-15
      • 1970-01-01
      • 2022-01-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多