WPF MVVM - 由于某种原因,ViewModels之间共享的集合

时间:2015-11-29 02:09:19

标签: wpf mvvm caliburn.micro

所以我有一个TabControl,它有一个ViewModel1实例作为每个标签。 ViewModel1的View有一个自定义的UserControl我构建,基本上暴露了DependencyProperty" Images"存储控件具有的图像列表。此属性已绑定(OneWayToSource)到ViewModel1的属性" Images"。

我遇到的问题是,由于某种原因,ViewModel1(所有标签)的所有实例都在共享此属性。因此,如果Tab1在控件中有1个图像,而Tab2在控件中有3个图像,那么"图像"每个ViewModel1实例的属性都有4个图像的集合。

我不知道会发生这样的事情 - 任何人都有任何想法吗?

请注意,我使用Caliburn.Micro作为MVVM框架。

编辑:控件内的属性定义如下:

public List<ImageData> Images
    {
        get { return (List<ImageData>)GetValue(ImagesProperty); }
        set { return; }
    }

    public static readonly DependencyProperty ImagesProperty =
        DependencyProperty.Register("Images", typeof(List<ImageData>), typeof(WebImageAlbum), 
            new UIPropertyMetadata(new List<ImageData>()));

只有使用Images.Add()添加新项目,并且在View的XAML中,此属性绑定到ViewModel&#34;图像&#34; Mode = OneWayToSource的属性。

编辑:这是UserControl的Tab视图:

<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
xmlns:local="clr-namespace:NET_MD3.Views"
xmlns:cal="http://www.caliburnproject.org" 
xmlns:CustomControls="clr-namespace:NET_MD3.CustomControls" x:Class="NET_MD3.Views.AlbumTabView"
mc:Ignorable="d" 
d:DesignHeight="267.789" d:DesignWidth="473.684">
<Grid>
    <CustomControls:WebImageAlbum x:Name="Album" Margin="10,10,10,50" Width="Auto" Height="Auto" ImageWidthHeight="95"
        cal:Message.Attach="[Event ImageClicked] = [Action ImageClicked($eventArgs)]"
        Images="{Binding Images, Mode=OneWayToSource}"/>
    <Button x:Name="CloseTab" Content="Close tab and delete album" HorizontalAlignment="Left" Margin="10,0,0,10" VerticalAlignment="Bottom" Width="172" Height="30"/>
    <Button x:Name="button" Content="Button" HorizontalAlignment="Left" Margin="342,243,0,0" VerticalAlignment="Top" Width="75" Click="button_Click"/>
</Grid>

这就是ViewModel的样子:

public class AlbumTabViewModel : Screen, IAlbumTabItem
{
    #region Constructor

    public AlbumTabViewModel(int id)
    {
        this.TabID = id;
    }

    #endregion

    #region Properties

    /// <summary>
    /// Get the Images loaded in this tab's Album (do not use the setter - it's for the Binding only)
    /// </summary>
    public List<ImageData> Images
    {
        get; set;
    }

    /// <summary>
    /// The Display name of this Screen (Tab)
    /// </summary>
    public override string DisplayName
    {
        get
        {
            return $"Album #{this.TabID}"; 
        }
        set { base.DisplayName = value; }
    }

    /// <summary>
    /// The ID of this tab
    /// </summary>
    public int TabID { get; private set; }

    #endregion

    #region Actions

    /// <summary>
    /// Delete this album tab
    /// </summary>
    public void CloseTab()
    {
        this.TryClose();
    }


    /// <summary>
    /// An image has been clicked within the album
    /// </summary>
    /// <param name="e"></param>
    public void ImageClicked(ImageData e)
    {
        //ttt
    }

    #endregion
}

1 个答案:

答案 0 :(得分:0)

结果证明问题出在DependencyProperty的声明中。在我传递给属性的静态声明的UIPropertyMetadata()中,我使用了一个'new List()'作为默认值,结果证明你不能真正做到这一点,因为它会将List创建为一个静态对象,它解释了为什么UserControl的每个实例都有相同的列表。这可能是因为DependencyProperty本身是静态的,因此当它尝试创建该默认值时,它也将是静态的。

我猜教训是在声明新的DependencyProperty时不要将引用类型作为默认值,如果必须,请将其设置在别处(在访问值的CLR属性中,或其他内容)。