0

TextBlock雇用されている労働者の数を反映するはずのプロパティにバインドされている WPF/MVVM (MVVM Light フレームワークを使用) にゲームがあります。バインディングが無傷であることを確認しましたが、更新できません。

これTextBlockが私の見解です:

<TextBlock x:Name="WorkersTextBlock"
           FontFamily="Pericles"
           DataContext="{Binding Guilds[0]}"
           Text="{Binding Workers.Count,
                          StringFormat=Workers : {0},
                          FallbackValue=Workers : 99}" />

ビューモデルのプロパティ:

public ObservableCollection<Guild> Guilds
{
    get { return DataManager.Data.Guilds; }
}

Workerまた、私のビューモデルでは、 aの Employer プロパティを変更するコマンド:

private void ExecuteHireWorkerCommand()
{
    if (SelectedWorker == null)
        return;

    SelectedWorker.Employer = DataManager.Data.Guilds[0];
    Gold -= SelectedWorker.Salary;
    _workerCollectionView.Refresh();
}

すべてのデータを保持するシングルトン クラスである DataManager では、次のようになります。

private ObservableCollection<Guild> _guilds = new ObservableCollection<Guild>();
public ObservableCollection<Guild> Guilds
{
    get { return _guilds; }
}

private ObservableCollection<Worker> _workers = new ObservableCollection<Worker>();
public ObservableCollection<Worker> Workers
{
    get { return _workers; }
}

Guildモデルでは:

public ObservableCollection<Worker> Workers
{
    get { return DataManager.Data.Workers.Where(w => w.Employer == this).ToObservableCollection(); }
}

の Employer プロパティWorkerは次のとおりです。

public Guild Employer { get; set; }

最後に、私の拡張メソッド (これが問題の原因だと思います):

public static ObservableCollection<T> ToObservableCollection<T>(this IEnumerable<T> source)
{
    if (source == null)
    {
        throw new ArgumentNullException("source");
    }
    return new ObservableCollection<T>(source);
}

メッセージボックスは、コマンドを介してWorker'Employer プロパティが適切に更新されていることを確認しますが、私が試したものは何も更新しませんTextBlock. RaisePropertyChangedここにリストしたすべてのものを実装しようとしましたが、うまくいきませんでした。

データの初期化時に、コンストラクター内での Employment プロパティをWorker正しいギルドに設定すると、数値はTextBlock正しく表示されますが、その後は更新されません。プロパティの LINQ フィルタリングと拡張メソッドWorkersがこの問題を引き起こしているのではないかと推測していますが、間違っている可能性もあります。

これを機能させる方法について誰かがアイデアを持っている場合は、ぜひ聞いてください。この問題に関するアドバイスは大歓迎です。さらにコードや情報が必要な場合は、お問い合わせください。

ありがとう。

更新: Ron は正しい道を進んでいると思います。拡張メソッドがバインディングを壊している可能性があります。Guildこの場合、バインディングを壊さずに Workers プロパティをフィルタリングする方法について誰かアドバイスをいただけますか? また、セッターの問題に関する限り、Workers プロパティにセッターを追加しましたが、実際には起動しません。

4

3 に答える 3

1

基礎となるデータ構造を少し再設計する必要があると思います。ただし、それが機能するように少し変更することはできます。

WorkersプロパティをICollectionView次のように変更します。

public ICollectionView Workers { get; set; }

次に、Guild モデルのコンストラクターで、次のようにデータ マネージャーからワーカー コレクションを設定できます。

Workers = CollectionViewSource.GetDefaultView(DataManager.Data.Workers);

ICollectionViewあなたのようなフィルターを追加してください:

Workers.Filter = (worker) => { return (worker.Employer == this); };

コレクションが更新さWorkers.Refresh()れるたびに呼び出します。Workers

そうすれば、バインディングが壊れることはなく、Workersコレクションは同じインスタンスを保持します。

ああ、バインディングに を追加UpdateSourceTrigger=PropertyChangedします。TextBox

私が言ったように、バッキングデータ構造を完全に再設計することを検討しますが、それを実装した理由や方法を知らなければ、それ以上のことは言えません.

于 2013-07-18T18:38:16.913 に答える
0

私はあなたのコードをテストしていませんが、モデルでは、 (拡張メソッドで見ることができます)をGuild返すとバインディングが壊れる可能性があります。バインドされたビューが常に元のインスタンスに関連付けられるように、少し再設計することをお勧めします.new ObservableCollectionObservableCollection

私はあなたのフレームワークを使用していませんが、MVVM パターンを実装するときは常に、ViewModel のオブザーバブルが同じインスタンスのままであることを確認し、メソッドを使用してClearメソッドの内容を置き換えOnModelChangedます。このような変更をビューに警告するために必要な通知を処理します。これは によって処理されますObservableCollection

于 2013-07-18T17:58:55.620 に答える