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 が含まれていることに注意してください。これも最初は正しくバインドされます)。

私の継承の実装についてはどうですか? 問題の原因を誤解している可能性はありますか?

編集: 以下のコメントのおかげで、 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 ではなく、セッターは PropertyChanged イベントを発生させます。

ただし、DataPointSubclass を使用する場合、PropertyChanged は常に null です (ただし、setter はトリガーされています)。ここで何が欠けているのでしょうか?

4

2 に答える 2

1

あなたのサービスコードは持っているObservableCollection<DataPoint>()ので、メソッドの戻り値の型はIQueryable<DataPoint>orだと思いますIEnumerable<DataPoint>

これを行うことにより、それが知っているビット (つまりDataPoint) のみをシリアル化し、他のメンバーを無視します。

正しくシリアル化するには、予想される型を派生クラスに変更する必要があります。

于 2012-08-15T21:08:21.013 に答える
0

これは、ツールが邪魔になる状況の 1 つです。

INotifyPropertyChanged サーバー側を実装する基本クラスがあります。私のサービスは、そのサブクラスであるオブジェクトのコレクションを返します。サブクラスであるため、クライアントは基本クラスにアクセスする必要があります。この問題を解決するために、サーバー側に実際に存在するクライアント側のファイルをリンクとして追加します。そうすれば、サービス参照を更新すると、クライアント側 (references.cs 内) に次のような部分クラスが生成されます。

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

DataPoint も実装していますが、INotifyPropertyChanged を実装していることを除けば、これは非常に優れた機能です。これは大したことではなく、私のすべての問題の根源でした。サブクラスで INPC を再実装すると (少なくとも基本クラスのプロパティを上書きせずに)、基本クラスの PropertyChanged は常に null になります。この場合、サービス参照は、基本クラスが既に実装しているかどうかを確認せずに INotifyPropertyChanged を自動的に実装しました。

解決策: References.svcmap でこの機能を無効にする必要があります。このプロパティを探して、falseに設定します。

<EnableDataBinding>true</EnableDataBinding>

ソリューション エクスプローラーですべてのファイルを表示し、サーバー参照ツリーを調べると、References.svcmap を見つけることができます。

これにより、サービス参照を更新することによって自動的に生成されたクラスは、INotifyPropertyChanged を自動的に実装しなくなります。その機能が必要な場合は、おそらく手動で実装する必要があります。

于 2012-08-16T16:54:42.780 に答える