[英]Bound property in WPF doesn't update
我的WPF / MVVM(帶有MVVM Light框架)游戲中有一個TextBlock
,它綁定到一個應該反映雇佣工人數量的屬性。 我已經確認綁定是完整的,但我無法更新它。
這是我視圖中的TextBlock
:
<TextBlock x:Name="WorkersTextBlock"
FontFamily="Pericles"
DataContext="{Binding Guilds[0]}"
Text="{Binding Workers.Count,
StringFormat=Workers : {0},
FallbackValue=Workers : 99}" />
我的viewmodel中的屬性:
public ObservableCollection<Guild> Guilds
{
get { return DataManager.Data.Guilds; }
}
同樣在我的viewmodel中,更改Worker
的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(); }
}
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);
}
Messageboxes確認通過該命令,正在更新Worker
的'Employer屬性,但我嘗試過的任何內容都不會使TextBlock
更新。 我已經嘗試在我列出的所有內容上實現RaisePropertyChanged
而沒有運氣。
如果我在初始化數據時將Worker
的Employment屬性設置為構造函數中的正確的guild,則TextBlock
的數字會正確顯示,但之后不會更新。 我的預感是Workers
屬性中的LINQ過濾和擴展方法導致了這個麻煩,但我可能是錯的。
如果有人對如何讓它發揮作用有任何想法,我很樂意聽到它們。 任何有關此事的建議都將不勝感激。 如果您需要更多代碼或信息,請詢問。
謝謝。
更新:我認為羅恩正走在正確的道路上; 擴展方法可能會打破綁定。 如果是這種情況,任何人都可以給我任何關於如何過濾Guild
的Workers屬性而不破壞綁定的建議嗎? 此外,就setter問題而言,我在Workers屬性中添加了一個setter,但它實際上從未觸發過。
public ObservableCollection<Worker> Workers
{
get { return DataManager.Data.Workers.Where(w => w.Employer == this).ToObservableCollection(); }
}
當此屬性實際更改時,您不會通知綁定系統。 如果基礎集合本身發生了變化,你會沒事的。 但是你甚至沒有保留對該底層集合的引用 - 你只是返回它。
正常模式會是這樣的(假設您在Guild
實現了INotifyPropertyChanged
)
private ObservableCollection<Worker> _Workers;
public ObservableCollection<Worker> Workers
{
get { return _Workers; }
set
{
if (value != _Workers)
{
_Workers = value;
NotifyPropertyChanged("Workers")
}
}
}
但這在某種程度上取決於你如何設置對象。 無論如何,您需要通知系統集合正在以某種方式發生變化。
編輯:你在評論中提到你使用了魔法。 我去看了文檔。 它說如何運作
5)顯式或隱式應用MagicAttribute轉換所有可用的公共屬性的setter。
你沒有在該屬性上設置setter,所以它不會修復它。
我認為你需要重新設計基礎數據結構。 但盡管如此,您可以稍微改變它以使其工作。
將Workers
屬性更改為ICollectionView
如下所示:
public ICollectionView Workers { get; set; }
然后在Guild模型的contstructor中,您可以從數據管理器填充workers集合,如下所示:
Workers = CollectionViewSource.GetDefaultView(DataManager.Data.Workers);
並向您的ICollectionView
添加一個過濾器,如下所示:
Workers.Filter = (worker) => { return (worker.Employer == this); };
每當更新Workers
集合時調用Workers.Refresh()
。
這樣你的綁定就不會破壞,你的Workers
集合將保留相同的實例。
哦,並將UpdateSourceTrigger=PropertyChanged
添加到TextBox
綁定中。
就像我說的那樣,我會考慮完全重新設計支持數據結構,但不知道為什么或如何實現它我不能說更多。
我還沒有測試過你的代碼,但是在Guild
模型中,返回一個new ObservableCollection
(可以在你的擴展方法中看到)可能會破壞你的綁定 ,我建議稍微重新設計一下,以便綁定視圖始終與原始視圖相關聯ObservableCollection
實例。
雖然我沒有使用你的框架,但是當我實現MVVM模式時,我總是確保我的ViewModel的observable仍然是同一個實例,並且我使用Clear
方法來替換我的OnModelChanged
方法中的內容,這樣你就不會必須處理警告視圖這些更改所需的通知,它由ObservableCollection
處理。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.