1

我正在使用来自 Esri 的地图,它提供了一个功能,您可以将集合绑定到地图,它为绘制和渲染图形点提供了所有魔力。它只要求对象具有一些要绑定的属性,如下所示:

<esri:PointDataSource
         ItemsSource="{Binding Path=PlottedData, Source={StaticResource ViewModel}, Mode=TwoWay}"
         XCoordinateBinding="{Binding X}"
         YCoordinateBinding="{Binding Y}"
         IsSelectedBinding="{Binding IsSelected, Mode=TwoWay}">

当然,我的应用程序需要的数据不仅仅是这些点,而且还有不同的类型。这导致我们为所有不同类型创建 DataPoint 的子类,然后将它们传递给地图,这样地图就不会更明智了。

我在没有子类的演示应用程序中很好地工作,但是当我将它合并到应用程序中并开始从服务作为子类接收数据时,IsSelected 功能停止工作。我可以确认所有点上的 IsSelected 属性正在按预期切换,但是当我切换它们时,它们不会反射回地图上。澄清一下,如果我在它们返回模型后用这个替换服务结果:

var returned = new ObservableCollection<DataPoint>()
    {
        new DataPoint(){IsPlottable = true, IsSelected = false, X = 722762, Y = 488253},
        new DataPoint(){IsSelected = false, X = 810000, Y = 550000, IsPlottable = true},
        new DataPoint(){IsSelected = false, X = 801000, Y = 480000, IsPlottable = true},
        new DataPoint(){IsSelected = false, X = 800100, Y = 500000, IsPlottable = true},
        new DataPoint(){IsSelected = false, X = 800010, Y = 506000, IsPlottable = true}
    };

然后它工作。然后当我用这个替换它时:

var returned = new ObservableCollection<DataPoint>()
    {
        new DataPointSubclass(){IsPlottable = true, IsSelected = false, X = 722762, Y = 488253},
        new DataPointSubclass(){IsSelected = false, X = 810000, Y = 550000, IsPlottable = true},
        new DataPointSubclass(){IsSelected = true, X = 801000, Y = 480000, IsPlottable = true},
        new DataPointSubclass(){IsSelected = false, X = 800100, Y = 500000, IsPlottable = true},
        new DataPointSubclass(){IsSelected = true, X = 800010, Y = 506000, IsPlottable = true}
    };

它停止工作。同时,这些点被正确绘制了——所以我知道绑定至少在创建绑定集合时是有效的(注意上面的子类是如何有一些 IsSelected = true; 最初也是正确绑定的)。

我的继承实现可能会导致绑定从基本上从单向/双向绑定切换到一次性绑定?我可以错误地归因于这个问题吗?

编辑:感谢下面的评论,我将其范围缩小到 PropertyChange 事件处理程序在设置 IsSelected 时为空。为清楚起见,这里是我在基类中定义 IsSelected 的公共成员的地方:

    [DataMember]
    public bool IsSelected
    {
        get { return _IsSelected; }
        set
        {
            if (_IsSelected != value)
            {
                _IsSelected = value;
                if (PropertyChanged != null)
                    PropertyChanged(this, new PropertyChangedEventArgs("IsSelected"));
            }
        }
    }

在我的演示应用程序中,一切正常,如果我使用上面的第一组虚拟点(有效),PropertyChanged 不为空,并且 setter 引发 PropertyChanged 事件。

但是,当使用 DataPointSubclass 时,PropertyChanged 始终为 null(但正在触发 setter)。我在这里能错过什么?

4

2 回答 2

1

您的服务代码有ObservableCollection<DataPoint>(),所以我猜该方法的返回类型是IQueryable<DataPoint>or IEnumerable<DataPoint>

通过这样做,它只是序列化它知道的位(即DataPoint)并忽略其他成员。

您需要将预期类型更改为派生类才能正确序列化。

于 2012-08-15T21:08:21.013 回答
0

这是我的工具妨碍的情况之一。

我有一个实现 INotifyPropertyChanged 服务器端的基类。我的服务返回一个对象集合,这些对象是它的子类。由于它是一个子类,我的客户需要访问基类。为了解决这个问题,我添加了一个真正存在于服务器端的文件客户端作为链接。这样,当我更新服务引用时,会在客户端(在references.cs中)生成一个部分类,它看起来有点像这样:

public partial class DataPointSubclass: Application.Server.Data.SharedCode.DataPoint, INotifyPropertyChanged { }

它是一个非常酷的功能,除了它实现了 INotifyPropertyChanged,尽管 DataPoint 也实现了它。这是一个很大的禁忌,是我所有问题的根源。当您在子类上重新实现 INPC(至少,不覆盖基类的属性)时,PropertyChanged 在基类中将始终为 null。在这种情况下,服务引用自动实现了 INotifyPropertyChanged,而不检查它的基类是否已经实现了它。

解决方案:您必须在 References.svcmap 中禁用此功能。查找此属性并将其设置为false

<EnableDataBinding>true</EnableDataBinding>

您可以通过在解决方案资源管理器中显示所有文件并查看服务器引用树来找到 References.svcmap。

通过这样做,通过更新服务引用自动生成的类不会自动实现 INotifyPropertyChanged。如果您想拥有该功能,您可能必须手动实现它。

于 2012-08-16T16:54:42.780 回答