【问题标题】:WPF MVVM - Collection shared between ViewModels for some reasonWPF MVVM - 出于某种原因在 ViewModel 之间共享的集合
【发布时间】:2015-11-29 02:09:18
【问题描述】:

所以我有一个 TabControl,每个选项卡都有一个 ViewModel1 实例。 ViewModel1 的 View 有一个我构建的自定义 UserControl,它基本上公开了一个 DependencyProperty “Images”,它存储了控件所具有的图像列表。此属性已绑定 (OneWayToSource) 到 ViewModel1 的属性“Images”。

我遇到的问题是,由于某种原因,ViewModel1 的所有实例(所有选项卡)都共享此属性。因此,如果 Tab1 在控件中有 1 张图片,而 Tab2 在控件中有 3 张图片,则每个 ViewModel1 实例的“Images”属性都有 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 中,此属性通过 Mode=OneWayToSource 绑定到 ViewModel 的“Images”属性。

编辑:这是带有 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
}

【问题讨论】:

  • 我的心理调试器说你有一个静态列表。没有我能做的最好的代码。
  • 总共有很多代码(视图、视图模型、自定义控件),所以很难说我应该放什么。不过,我已经添加了“Images”依赖属性的声明,所以你可以看一下(它不是静态的)。
  • 你为什么把它设为 DependencyProperty 而不是简单地绑定?
  • @Fabis ViewModel 的代码,更新列表的代码,至少是 XAML
  • 我将其设为 DependencyProperty,因此我可以通过 XAML 绑定到它,我不想在代码隐藏中做任何事情。

标签: wpf mvvm caliburn.micro


【解决方案1】:

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

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

【讨论】:

    猜你喜欢
    • 2011-07-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-03-13
    • 2019-07-02
    • 2010-11-12
    • 2012-11-27
    相关资源
    最近更新 更多