从一个PointCollection中绘制两条折线会引发异常(Silverlight 5)

时间:2012-01-11 13:59:07

标签: silverlight mvvm singleton polyline

我正在使用Silverlight 5和MVVM。

我有一个 Singleton 的ViewModel。 ViewModel公开了我用于在我的一个视图中绘制PointCollection的{​​{1}}。

如果我尝试在第二个视图中绘制相同的Polyline,再次通过数据绑定到Polyline,我会得到“值不在预期范围内”的异常。

据我所知(使用我有限的Silverlight知识),这是由于PointCollection无法共享这一事实造成的。

有解决方法吗?如何绘制与第一个相同的第二个折线?我希望同时将两条折线数据绑定到一个PointCollection

编辑:我找不到解决方案,但遇到同样问题的人here。根据微软的说法:

  

此MSDN页面提到某些对象不可共享,并且会产生“超出范围的值”异常。   PointCollections

     

PointCollection页面还提到它不可共享。   http://msdn.microsoft.com/en-us/library/system.windows.resourcedictionary(VS.95).aspx

     

目前,这是出于设计行为。但是,我们正在对此进行评估,以确定我们是否可以更改行为或至少更改异常文本。

3 个答案:

答案 0 :(得分:1)

我找到了解决方案here:复制了getter中的PointCollection。

    private PointCollection sourcePoints;
    public PointCollection SourcePoints
    {
        get
        {
            // create a new instance of PointCollection for binding
            PointCollection newPoints = new PointCollection();
            foreach (Point p in sourcePoints)
            {
                newPoints.Add(p);
            }
            return newPoints;
        }

答案 1 :(得分:0)

也许你的PointCollection已经冻结,这就是麻烦。

MSDN:

Freezable功能:因为它继承自Freezable类,所以PointCollection类提供了几个特殊功能:PointCollection对象可以声明为资源,在多个对象之间共享,使其成为只读以提高性能,克隆并使线程安全。有关Freezable对象提供的不同功能的更多信息,请参阅Freezable Objects Overview。

答案 2 :(得分:0)

看一下这个问题:Why doesn't this data binding work?

此时也是:2nd time binding to PointCollection not being rendered

由于您提供的细节很少,我不太确定发生了什么,但这些帖子可能有所帮助。如果没有,请发布您的代码。

我做了一些测试,我能想到的最佳解决方案是:

using System.ComponentModel;
using System.Windows;
using System.Windows.Media;

namespace SilverlightApplication6
{
    public class DemoVM : INotifyPropertyChanged
    {
        #region PointsClone Property
        private PointCollection _pointsClone;
        public PointCollection PointsClone
        {
            get
            {
                return _pointsClone;
            }
            set
            {
                if (_pointsClone != value)
                {
                    _pointsClone = value;
                    OnPropertyChanged("PointsClone");
                }
            }
        }
        #endregion

        #region Points Property
        private PointCollection _points;
        public PointCollection Points
        {
            get
            {
                return _points;
            }
            set
            {
                if (_points != value)
                {
                    _points = value;
                    PointsClone.Clear();
                    foreach (var point in _points)
                    {
                        PointsClone.Add(point);
                    }
                    OnPropertyChanged("Points");
                }
            }
        }
        #endregion

        public DemoVM()
        {
            PointsClone = new PointCollection();
            Points = new PointCollection();
        }

        public void AddPoint(Point point)
        {
            Points.Add(point);
            PointsClone.Add(point);
        }

        public void ClearPoints()
        {
            Points.Clear();
            PointsClone.Clear();
        }


        public event PropertyChangedEventHandler PropertyChanged;

        protected void OnPropertyChanged(string propertyName)
        {
            var p = PropertyChanged;
            if (p != null)
            {
                p(this, new PropertyChangedEventArgs(propertyName));
            }
        }
    }
}

将一个PolyLine.Points绑定到Points,将另一个PolyLine.Points绑定到PointsClone。

它有点难看,因为当你使用vm.Points.Add(point)而不是vm.AddPoint(point)时它会破坏。通过应用适当的封装,您可以解决这个问题。