我正在使用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
目前,这是出于设计行为。但是,我们正在对此进行评估,以确定我们是否可以更改行为或至少更改异常文本。
答案 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)时它会破坏。通过应用适当的封装,您可以解决这个问题。