簡體   English   中英

WPF中的綁定屬性不會更新

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM