简体   繁体   English

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

[英]Silverlight - Binding issue when using inheritence

I'm using a map from Esri, which offers a feature where you can bind a collection to the map, and it does all the magic for plotting and rendering graphic points. 我正在使用Esri中的地图,该地图提供了一项功能,您可以在其中将集合绑定到地图,并且它具有绘制和渲染图形点的所有魔力。 It just requires that the object has some properties to bind to, as shown below: 它只需要对象具有一些要绑定的属性,如下所示:

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

My application, of course, requires more data than just those points, and there are different types too. 当然,我的应用程序不仅需要这些数据,还需要更多数据,并且类型也不同。 This lead us to make subclasses of DataPoint for all of the different types, and then pass them through such that the map wouldn't be the wiser. 这导致我们为所有不同类型创建DataPoint的子类,然后将它们传递给子对象,以使映射不会更明智。

I had this working wonderfully in a demo application without the subclasses, but when I incorporate this into the application, and start receiving data from the services as a subclass, the IsSelected functionality stops working. 在没有子类的演示应用程序中,我的工作非常出色,但是当我将其合并到应用程序中并开始以子类的形式从服务接收数据时,IsSelected功能将停止工作。 I can confirm that the IsSelected properties on all of the points is being toggled when expected, but when i toggle them, they aren't reflected back onto the map. 我可以确认所有点的IsSelected属性都可以按预期进行切换,但是当我切换它们时,它们不会反映回地图上。 To clarify, if I replace the service results with this AFTER they're returned to the model : 为了澄清,如果在此之后我将服务结果替换为服务结果, 它们将返回模型

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}
    };

then it works. 然后就可以了。 WhenI then replace that with this: 当我然后用这个替换它时:

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}
    };

it stops working. 它停止工作。 Meanwhile, the points are plotted correctly--so I know that the binding is working at least when the bound collection is created (notice how the subclass above has some IsSelected = true; that binds right initially too). 同时,正确绘制了点-因此,我知道绑定至少在创建绑定集合时有效(请注意,上面的子类如何具有一些IsSelected = true;最初也正确绑定)。

What about my inheritence implementation might be causing the binding from basically switch from one/two-way binding to one-time binding? 我的继承实现可能会导致绑定从基本上从单向/双向绑定切换到一次性绑定? Could I be misattributing the issue? 我可以错误地分配问题吗?

EDIT : Thanks to comments below, I've narrowed it down to PropertyChange event handler being null whenever IsSelected is set. 编辑 :感谢下面的评论,每当设置IsSelected时,我都将其范围缩小为PropertyChange事件处理程序,它为null。 For clarity, here is where I define the public member of IsSelected in the base class: 为了清楚起见,这是在基类中定义IsSelected的公共成员的位置:

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

In my demo app, where everything works, and if I use the first set of dummy points above (which work), PropertyChanged is not null, and the setter raises the PropertyChanged event. 在演示应用程序中,一切正常,如果我使用上面的第一组虚拟点(有效),则PropertyChanged不为null,并且setter引发PropertyChanged事件。

When using a DataPointSubclass, however, PropertyChanged is always null (but the setter is being triggered). 但是,在使用DataPointSubclass时,PropertyChanged始终为null(但将触发设置器)。 What could I be missing here? 我在这里可能想念什么?

Your service code has ObservableCollection<DataPoint>() so I am guessing the return type of the method is IQueryable<DataPoint> or IEnumerable<DataPoint> . 您的服务代码具有ObservableCollection<DataPoint>()因此我猜测该方法的返回类型为IQueryable<DataPoint>IEnumerable<DataPoint>

By doing this it is only serializing the bits it knows about (ie DataPoint ) and ignoring the other members. 通过这样做,它只是序列化它知道的位(即DataPoint ),而忽略其他成员。

You need to change the expected type to be the derived class for it to serialise correctly. 您需要将期望的类型更改为派生类,以使其正确序列化。

The is one of those situations where my tools got in the way. 这是我的工具受阻的情况之一。

I have a base class that implements INotifyPropertyChanged server side. 我有一个实现INotifyPropertyChanged服务器端的基类。 My service returns a collection of objects which are a subclass of it. 我的服务返回对象的集合,这些对象是其子类。 Since its a subclass, my client needs access to the base-class. 由于它是子类,因此我的客户需要访问基类。 To solve this problem, I Add as Link a file client-side which really exists server-side. 为了解决该问题,我将确实存在于服务器端的文件客户端添加为链接。 That way, when I update service references, a partial class is generated client-side (in references.cs) which looks a bit like this: 这样,当我更新服务引用时,将在客户端(在references.cs中)生成部分类,看起来像这样:

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

Its a pretty cool feature, except that it implements INotifyPropertyChanged, even though DataPoint also implements it. 它是一个很酷的功能,除了它实现INotifyPropertyChanged之外,即使DataPoint也实现了它。 This is a big no-no, and was the root of all my problems. 这是一个很大的禁忌,这是我所有问题的根源。 When you re-implement INPC on a subclass (at least, without overwriting the base class' property), PropertyChanged will always be null in the base class . 当您在子类上重新实现INPC时(至少不覆盖基类的属性),PropertyChanged在基类中始终为null In this case, the service reference automatically implemented INotifyPropertyChanged without checking if its base class already implemented it. 在这种情况下,服务引用会自动实现INotifyPropertyChanged,而无需检查其基类是否已经实现了它。

Solution : You have to disable this feature in References.svcmap. 解决方案 :您必须在References.svcmap中禁用此功能。 Look for this property and set it to false : 查找此属性并将其设置为false

<EnableDataBinding>true</EnableDataBinding>

You can find References.svcmap by showing all files in solution explorer, and looking in your server references tree. 通过在解决方案资源管理器中显示所有文件,然后在服务器引用树中查找,可以找到References.svcmap。

By doing this, classes automatically generated by updating your services references wont implement INotifyPropertyChanged automatically. 这样,通过更新服务引用自动生成的类将不会自动实现INotifyPropertyChanged。 If you want to have that functionality, you would presumably have to implement it manually. 如果要具有该功能,则可能必须手动实施。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM