在WPF属性设置器中指定集合

时间:2014-05-12 20:12:29

标签: wpf wpf-controls

我有一个图例上项目的依赖属性。它看起来像:

    public List<LegendItem> LegendItems
    {
        get { return (List<LegendItem>)GetValue(LegendItemsProperty); }
        set { SetValue(LegendItemsProperty, value); }
    }

    // Using a DependencyProperty as the backing store for MyProperty.  This enables animation, styling, binding, etc...
    public static readonly DependencyProperty LegendItemsProperty =
        DependencyProperty.Register("LegendItems", typeof(List<LegendItem>), typeof(TipScoreboard), new PropertyMetadata());

其中LegendItemUserControl

我可以像这样在XAML中设置它没有任何问题。

<local:TipScoreboard.LegendItems>
    <local:LegendItem ItemFillBrush="{DynamicResource GreenStatusBrush}"
                      Label="{x:Static res:TipLabels.GoodScan}"/>
    <local:LegendItem ItemFillBrush="{DynamicResource RedStatusBrush}"
                      Label="{x:Static res:TipLabels.BadScan}"/>
</local:TipScoreboard.LegendItems>

但是当我在这样的setter中设置这个属性时:

<Setter Property="LegendItems">
     <Setter.Value>
         <local:LegendItem ItemFillBrush="{DynamicResource GreenStatusBrush}"
                           Label="{x:Static res:TipLabels.GoodScan}"/>
         <local:LegendItem ItemFillBrush="{DynamicResource YellowStatusBrush}"
                           Label="{x:Static res:TipLabels.LowConfidence}"/>
      </Setter.Value>
 </Setter>

我获得了设置者的The property "Value" is set more than once.。我不知道如何包装这个或做什么。我试过在它周围包装一个List,但这似乎不起作用。

编辑:我尝试创建自定义包装的集合,所有内容都符合并运行但内容为空。

public class LegendItemCollection : Collection<LegendItem>
{
}

public LegendItemCollection LegendItems
{
    get { return (LegendItemCollection)GetValue(LegendItemsProperty); }
    set { SetValue(LegendItemsProperty, value); }
}

 public static readonly DependencyProperty LegendItemsProperty =
        DependencyProperty.Register("LegendItems", typeof(LegendItemCollection), typeof(TipScoreboard), new PropertyMetadata());

和XAML:

<Setter Property="LegendItems">
    <Setter.Value>
       <local:LegendItemCollection>
           <local:LegendItem ItemFillBrush="{DynamicResource GreenStatusBrush}"
                             Label="{x:Static res:TipLabels.GoodScan}"/>
           <local:LegendItem ItemFillBrush="{DynamicResource YellowStatusBrush}"
                             Label="{x:Static res:TipLabels.LowConfidence}"/>
       </local:LegendItemCollection>
    </Setter.Value>
</Setter>

1 个答案:

答案 0 :(得分:6)

处理此问题的一种方法是将依赖项属性的类型更改为包装List<LegendItem>的类:

public class LegendItemCollection : List<LegendItem>
{
}

public LegendItemCollection LegendItems
{
    get { return (LegendItemCollection)GetValue(LegendItemsProperty); }
    set { SetValue(LegendItemsProperty, value); }
}
public static readonly DependencyProperty LegendItemsProperty =
    DependencyProperty.Register("LegendItems", typeof(LegendItemCollection), typeof(TipScoreboard), 
        new PropertyMetadata((sender, args) => {
            System.Diagnostics.Debug.WriteLine("LegendItems property set");
        }));

然后,您可以在XAML中直接设置属性:

<Setter Property="LegendItems">
     <Setter.Value>
         <local:LegendItemCollection>
             <local:LegendItem ItemFillBrush="{DynamicResource GreenStatusBrush}"
                               Label="{x:Static res:TipLabels.GoodScan}"/>
             <local:LegendItem ItemFillBrush="{DynamicResource YellowStatusBrush}"
                               Label="{x:Static res:TipLabels.LowConfidence}"/>
         </local:LegendItemCollection>
      </Setter.Value>
 </Setter>

我相信,理论上,您可以在不需要包装器集合类的情况下实现相同的功能,并使用x:TypeArguments在XAML中声明List<T>。我似乎无法让这个工作起来(related question)。根据文件,声明看起来像这样:

<Setter Property="LegendItems">
     <Setter.Value>
         <scg:List xmlns:scg="clr-namespace:System.Collections.Generic;assembly=mscorlib"
                   x:TypeArguments="local:LegendItem">
             <local:LegendItem ItemFillBrush="{DynamicResource GreenStatusBrush}"
                               Label="{x:Static res:TipLabels.GoodScan}"/>
             <local:LegendItem ItemFillBrush="{DynamicResource YellowStatusBrush}"
                               Label="{x:Static res:TipLabels.LowConfidence}"/>
         </scg:List>
      </Setter.Value>
 </Setter>

但是,上面的代码给了我一个编译器错误:

  

命名空间'clr-namespace中不存在名称'List':System.Collections.Generic; assembly = mscorlib'


修改

根据评论,OP中编辑的解决方案是使用SetCurrentValue而不是直接分配属性(后者会因dependency property value precedence而消除属性上的任何样式):

this.SetCurrentValue(LegendItemsProperty, new LegendItemCollection());