Silverlight - 使用继承时的绑定问题

时间:2012-08-15 20:47:18

标签: c# wpf silverlight binding esri

我正在使用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;这也是最初绑定的。)

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

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

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

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

但是,在使用DataPointSubclass时,PropertyChanged始终为null(但正在触发setter)。我可以在这里找到什么?

2 个答案:

答案 0 :(得分:1)

您的服务代码为ObservableCollection<DataPoint>(),因此我猜测该方法的返回类型为IQueryable<DataPoint>IEnumerable<DataPoint>

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

您需要将预期类型更改为派生类,以使其正确序列化。

答案 1 :(得分: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。如果你想拥有这个功能,你可能必须手动实现它。