使用ObservableCollection类型的DependencyProperty创建CustomUserControl

时间:2013-07-07 19:41:03

标签: .net wpf xaml data-binding

我正在尝试在WPF中创建一个CustomUserControl。 此CustomUserControl包含ObservableCollection类型的DependencyProperty。

我的目标是能够:

  • 能够直接在xaml代码中设置集合
  • 能够将集合绑定到我的ViewModel
  • 中的集合
  • 能够使用样式设定器
  • 设置集合
  • 每个CustomUserControl实例都有一个不同的集合实例。

这就是我现在所拥有的:

<my:CustomUserControl ImageList={Binding imgList}/>

ImageList定义如下:

public static readonly DependancyProperty ImageListProperty = DependancyProperty.Register
  ("ImageList", typeof(List<ImageSource>), typeof(Switch));

public List<ImageSource> ImageList {
  get { return (List<ImageSource>)GetValue(ImageListProperty); }
  set { SetValue(ImageListProperty, value); }
}

为了在每个CustomUserControl中有一个新的ImageList实例,我在CustomUserControl的ctor中添加了以下行:

public CustomUserControl(){
...
SetValue(ImageListProperty, new List<ImageSource>());
}

现在,以下代码示例有效:

<my:CustomUserControl>
  <my:CustomUserControl.ImageList>
    <BitmapImage UriSource="Bla.png"/>
    <BitmapImage UriSource="Bla2.png"/>
  </my:CustomUserControl.ImageList>
</my:switch>

这也有效:

<my:CustomUserControl ImageList={Binding imgList}/>

<Style TargetType="my:CustomUserControl">
<Setter Property="my:CustomUserControl.ImageList">
        <BitmapImage UriSource="Bla.png"/>
        <BitmapImage UriSource="Bla2.png"/>
</Setter>
</Style>

这使得所有实例都留有空的ImageList。

P.S。这是伪代码,因为我不记得确切的语法。

谢谢!

2 个答案:

答案 0 :(得分:1)

您无法在Style中设置值的原因是您在构造函数中设置了本地值。 MSDN explains DependencyProperty value precedence in more detail

因为您只想为每个实例赋予属性默认值,所以只需在构造函数中使用SetCurrentValue而不是SetValue

编辑以进一步解释

因此,可以通过多种方式设置DependencyProperty。它可以通过代码设置,BindingStyleTriggerAnimation或其他一些方式。重要的是要知道可以多次尝试设置给定的属性。

因此,WPF已为这些值定义了优先级。这意味着如果您在Style中设置属性,则可以手动设置属性以覆盖Style值。或者Trigger中的ControlTemplate可以覆盖Style值。

在构造函数中设置属性时,您将为其提供本地值。在第一个链接中,您会看到 AnimationProperty Coercion可以覆盖本地值。

但是,SetCurrentValue方法允许您为属性without setting a local value设置值。这就是您所需要的,因为您希望能够在Style中设置值。

答案 1 :(得分:0)

您应该使用List<ImageSource>msdn

而不是CompositeCollection
public CompositeCollection ImageList
{
    get { return (CompositeCollection)GetValue(ImageListProperty); }
    set { SetValue(ImageListProperty, value); }
}      
public static readonly DependencyProperty ImageListProperty =
    DependencyProperty.Register("ImageList", typeof(CompositeCollection), typeof(CustomUserControl), new PropertyMetadata(new CompositeCollection()));

现在您可以按照以下定义的样式设置值:

<my:CustomUserControl x:Name="myCustomUserControl   
    <my:CustomUserControl.Style>
        <Style TargetType="{x:Type my:CustomUserControl}">
            <Setter Property="my:CustomUserControl.ImageList">
                <Setter.Value>
                    <CompositeCollection>
                        <BitmapImage UriSource="Bla.png"/>
                        <BitmapImage UriSource="Bla2.png"/>
                    </CompositeCollection>
                </Setter.Value>
            </Setter>
        </Style>
    </my:CustomUserControl.Style>            
</my:CustomUserControl>

其他绑定的工作方式与您在问题中提供的方式相同。

e.g:

<my:CustomUserControl x:Name="myCustomUserControl">
    <my:CustomUserControl.ImageList>
        <BitmapImage UriSource="Bla.png" />
        <BitmapImage UriSource="Bla2.png" />
    </my:CustomUserControl.ImageList>            
</my:CustomUserControl>