【问题标题】:Drawing two polylines from one PointCollection throws exception (Silverlight 5)从一个 PointCollection 绘制两条折线会引发异常 (Silverlight 5)
【发布时间】:2012-01-11 13:59:07
【问题描述】:

我正在使用带有 MVVM 的 Silverlight 5。

我有一个 Singleton 的 ViewModel。 ViewModel 公开了一个PointCollection,我用它来在我的一个视图中绘制一个Polyline

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

据我所知(以我有限的 Silverlight 知识),这是因为 PointCollections 不可共享。

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

编辑:我还没有找到解决方案,但是有人遇到了同样的问题here。据微软称:

此 MSDN 页面提到某些对象不可共享,并且会生成“值超出范围”异常。 http://msdn.microsoft.com/en-us/library/system.windows.resourcedictionary(VS.95).aspx

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

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

【问题讨论】:

    标签: silverlight mvvm singleton polyline


    【解决方案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;
            }
    

    【讨论】:

      【解决方案2】:

      看看这个问题: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) 时它会中断。通过应用适当的封装,您也许可以解决这个问题。

      【讨论】:

      • 谢谢,我以前读过这两个主题,但它们对我没有帮助。第一个是关于PointCollection 的变化。第二个处理将PointCollection 绑定到折线,然后删除绑定,然后恢复绑定,因此两条折线绝不会同时访问PointCollection
      • 非常感谢 Erno!在看到您的更新之前,我也刚刚找到了一个非常相似的解决方案。
      • 请注意,您发布的解决方案不会跟踪更改!
      【解决方案3】:

      也许您的 PointCollection 已被冻结,这造成了麻烦。

      MSDN:

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

      【讨论】:

      • “Silverlight 在其对象模型中不包括可冻结对象。有关详细信息,请参阅 WPF 文档中的可冻结对象概述。”
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-11-22
      • 1970-01-01
      • 2020-10-19
      • 1970-01-01
      相关资源
      最近更新 更多