web-dev-qa-db-ja.com

データバインドされたWPF ListBoxを強制的に更新するより良い方法?

ObservableCollectionにバインドされているWPF ListBoxがあります。コレクションが変更されると、すべてのアイテムがその位置を更新します。

新しい位置はコレクションに保存されますが、UIは更新されません。だから私は以下を追加しました:

    void scenarioItems_CollectionChanged(object sender, System.Collections.Specialized.NotifyCollectionChangedEventArgs e)
    {
        ToolboxListItem.UpdatePositions();
        lstScenario.ItemsSource = null;
        lstScenario.ItemsSource = ToolboxListItem.ScenarioItems;
        this.lstScenario.SelectedIndex = e.NewStartingIndex;
    }

ItemsSourceをnullに設定してから再度バインドすると、UIが更新され、

しかし、これはおそらく非常に悪いコーディングです:p

提案?

30
TimothyP

タイプList<MyCustomType>()のオブジェクトプロパティにバインドされたリストボックスがあり、リストが更新されると、次のコードがリストボックスを更新することを確認しました。

void On_MyObjProperty_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
   MyListBox.Items.Refresh();
}

それでも問題が解決しない場合は、VS IDE出力ウィンドウ(Ctrl + W、O)をスキャンして、報告されたバインディングエラーを見つけられるかどうかを確認してください。

75
Gishu

リスト/アイテムのコレクションをListBoxにバインドするWPFが、アイテムが更新された後、UIが更新されない解決済み

私はただ愚かです。 _ObservableCollection<>_の代わりに_List<>_の使用について多くを読みましたが、この提案を無視し続け、他の提案に従いましたが、役に立ちませんでした。私の本に戻って読み直してください。 _ObservableCollection<>_は、コレクション内のアイテムが変更されたときにINotifyCollectionChangeが表示を更新するために必要なListBoxインターフェースを提供しないため、_List<>_は必須の要素であることは十分に説明されています。

これは更新されたコードです:

_private ObservableCollection<StringWrapper> m_AppLog;
ObservableCollection<StringWrapper> Log { get { return m_AppLog; } }
_

かなりシンプルで、他に何も必要としません(Refresh()など)。 ObservableCollection自体が変更イベントのトリガーを処理するため、不要な呼び出しを削除できました。

_// notify bound objects
OnPropertyChanged("Log");
_

ObservableCollectionは、それを作成しなかったスレッドによる更新をサポートしていません。リスト(最近のエラー/情報メッセージを表示するビジュアルログ)は異なるスレッドから更新できるため、コードをこのように調整して、リストの独自のディスパッチャーで更新が行われたことを確認します。

_public void AddToLog(string message) {
    if (Thread.CurrentThread != Dispatcher.Thread) {
        // Need for invoke if called from a different thread
        Dispatcher.Invoke(
            DispatcherPriority.Normal, (ThreadStart)delegate() { AddToLog(message); });
    }
    else {
        // add this line at the top of the log
        m_AppLog.Insert(0, new StringWrapper(message));
        // ...
_

また、_ObservableCollection<>_は_List<>_とは異なり、RemoveRange()をサポートしていません。これは、ListからObservableCollectionに切り替えるときに必要な調整の一部です。

10
rolling

私はあなたと同じような問題を抱えているかもしれませんが、よくわかりません。

ObservableCollection<MyEntity>とそれにバインドされているListBox。しかし、いくつかの奇妙な理由のために、リスト内のListBoxオブジェクトのプロパティを変更したときに、MyEntityが更新されていませんでした。

しばらく検索したところ、次のページが見つかりましたのでお知らせください。

http://www.wblum.org/listbind/net3/index.html

これは、リストまたはリスト内のオブジェクトが変更されたときにListBoxを更新するために行う必要があることを非常によく説明しています。あなたがこれから利益を得ることを願っています。

私は昨日同じ問題を抱えていましたが、それは完全ながらくたの一部です:) ...私はもう私のものをnullに設定していません。私のシナリオでは、(リストに追加するたびに)MyList.ToArray()に設定しています。

私は複数の「ああ、あなたはObservableListを使用する必要がある」<-完全ながらくたを見てきました。

私は複数の「ああ、「リフレッシュ」を呼び出す」<-完全ながらくたを見た。

私の動揺を許してください、しかし私はこれがうまくいくことも期待します:)

4
Timothy Khouri

これは古いものですが、ObservableCollectionを使用してください。 ObservableCollectionのオブジェクトのプロパティの更新をUIに表示させる場合は、そのオブジェクトのクラス定義にINotifyPropertyChangedを実装する必要があります。次に、各プロパティのセッターでプロパティ変更イベントを発生させます。

Public Class Session
Implements INotifyPropertyChanged

Public Event PropertyChanged As PropertyChangedEventHandler _
   Implements INotifyPropertyChanged.PropertyChanged

Private Sub NotifyPropertyChanged(ByVal info As String)
    RaiseEvent PropertyChanged(Me, New PropertyChangedEventArgs(info))
End Sub

Private _name As String = "No name"
''' <summary>
''' Name of Session
''' </summary>
''' <value></value>
''' <returns></returns>
''' <remarks></remarks>
Public Property Name() As String
    Get
        Return _name
    End Get
    Set(ByVal value As String)
        _name = value
        NotifyPropertyChanged("Name")
    End Set
End Property
2
KP.

私には、ListBoxとListViewのバグのように見えます。 ObservableCollectionにバインドしています。コレクション内のアイテムはINotifyPropertyChangedを実装しています。 「アイテムの追加」ボタンを動的に押すと、UIに追加アイテムが表示されませんが、MyCollection.Countにバインドされているカウンターコントロールがあります。このカウンターコントロールは、[アイテムの追加]ボタンを押すたびに増加します。ビューのサイズを変更すると、リストボックスに追加したすべてのアイテムが表示されます。そのため、ListBoxコントロールのItemSourceバインディングは壊れています。また、バインディングを壊すような新しいMyCollectionを作成しないように注意しました。ブーフー。

0
flobadob

オブジェクトのObservableListがあり、それらのオブジェクト内のプロパティを変更している場合、コレクションは直接変更されないため、通知は適用されません。 Insert()を使用してオブジェクトのプロパティを変更した後、変更されたオブジェクトをコレクションに再度追加し、RemoveAt()を使用して古いコピーを削除することで、通知を強制しています。きれいではありませんが、動作します。

0
Peter