wpf - 在 WPF Property setter 中指定集合

标签 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());

其中 LegendItem 是一个 UserControl

我可以毫无问题地在 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. 为 setter。我不确定如何包装这个或做什么。我试过只用一个 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>

最佳答案

处理此问题的一种方法是将依赖属性的类型更改为包装 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>

我相信,理论上,您可以在不需要包装器集合类的情况下实现相同的目的,声明一个 List<T>。在 XAML 中使用 x:TypeArguments .不过,我似乎无法让它工作(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>

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

The name 'List' does not exist in the namespace 'clr-namespace:System.Collections.Generic;assembly=mscorlib'


编辑

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

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

关于wpf - 在 WPF Property setter 中指定集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/23618006/

相关文章:

c# - 按字母顺序添加到 ObservableCollection

wpf - 如何在 WPF 自定义控件中填充集合控件?

.net - 扩展器旧子弹仍然显示

WPF:集合依赖属性 "is read-only and cannot be set from markup"

c# - wpf如何控制 Storyboard

2个方向的WPF渐变

WPF - 在 xaml 中完成另一个动画后开始动画

c# - 第 1 行 'date' 列的日期时间值不正确

wpf - 如何在WPF中将焦点添加到可编辑的组合框

c# - 如何按类型获取 WPF 容器的子容器?