データバインドされたWPF ListBoxを強制的に更新するより良い方法は?
-
05-07-2019 - |
質問
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
提案?
解決
タイプList<MyCustomType>()
のオブジェクトプロパティにバインドされたリストボックスがあり、リストの更新時に次のコードがリストボックスを更新することを確認しました。
void On_MyObjProperty_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
MyListBox.Items.Refresh();
}
まだ問題に直面している場合は、VS IDE出力ウィンドウ(Ctrl + W、O)をスキャンし、報告されたバインディングエラーを見つけることができるかどうかを確認します。
他のヒント
WPFはリスト/アイテムのコレクションをListBoxにバインドしますが、アイテムが更新された後にUIが更新されない、解決。
私はただ愚かだ。 ObservableCollection<>
の代わりにList<>
を使用することについて多くのことを読みましたが、私はこの提案を無視し続け、他の提案に従いました。私の本に戻って読み直しました。コレクション内のアイテムが変更されたときにINotifyCollectionChange
がその表示を更新するために必要なListBox
インターフェースをObservableCollection
が提供しないため、RemoveRange()
は必ず使用する必要があることは十分に説明されています。
これは更新されたコードです:
private ObservableCollection<StringWrapper> m_AppLog;
ObservableCollection<StringWrapper> Log { get { return m_AppLog; } }
非常にシンプルで、他に何も必要ありません(Refresh()など)。 ObservableCollectionがchangeイベントのトリガーを処理するため、不要な呼び出しを削除できました。
// notify bound objects
OnPropertyChanged("Log");
<=>は、それを作成しなかったスレッドによる更新をサポートしていません。リスト(最近のエラー/情報メッセージを表示する視覚的なログ)は異なるスレッドから更新できるため、リストのディスパッチャで更新が行われるようにコードをこのように調整します:
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));
// ...
また、<=>は<=>に反して<=>をサポートしないことに注意してください。これは、ListからObservableCollectionに切り替えるときに必要な調整の一部です。
あなたが持っているものと同様の問題を抱えているかもしれませんが、よくわかりません。
ObservableCollection<MyEntity>
とListBox
がバインドされていました。しかし、何らかの奇妙な理由のために、リスト内のMyEntity
オブジェクトのプロパティを変更しても<=>が更新されませんでした。
しばらく検索した後、私は次のページを見つけたので、あなたに知らせる必要がありました:
http:/ /www.wblum.org/listbind/net3/index.html
これは、リストまたはリスト内のオブジェクトが変更されたときに<=>を更新するために何をしなければならないかについての非常に良い説明です。この恩恵を受けることを願っています。
昨日も同じ問題が発生しましたが、完全ながらくたです:) ...私はもうnullに設定していません。私のシナリオでは、MyList.ToArray()に設定しています(リストに追加するたびに)。
複数の<!> quot;を見ました。ああ、ObservableList <!> quotを使用する必要があります。 <!> lt;-完全ながらくた。
複数の<!> quot;ああ、 'Refresh' <!> quotを呼び出しました; <!> lt;-完全ながらくた。
動揺をお許しください。しかし、これが機能することも期待しています:)
これは古いものですが、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
オブジェクトのObservableListがあり、それらのオブジェクト内のプロパティを変更している場合、コレクションは直接変更されないため、通知は適用されません。 Insert()を使用して変更したオブジェクトをコレクションに再追加し、RemoveAt()を使用して古いコピーを削除することにより、オブジェクトのプロパティを変更した後に通知を強制しました。きれいではありませんが、動作します。
私にとっては、ListBoxとListViewのバグのように見えます。私はObservableCollectionにバインドしています。コレクション内のアイテムはINotifyPropertyChangedを実装しています。 「アイテムの追加」ボタンを動的に押すと、UIに追加されたアイテムは表示されませんが、MyCollection.Countにバインドされたカウンターコントロールがあります。このカウンターコントロールは、[アイテムの追加]ボタンを押すたびに増加します。ビューのサイズを変更すると、追加されたすべてのアイテムがリストボックスに表示されます。そのため、ListBoxコントロールのItemSourceバインディングが壊れています。また、どの時点でも新しいMyCollectionを作成しないように注意しました。これにより、バインドが解除されます。ブーフー。