[英]ObservableCollection<DateTime> and updating the UI when the item changes
[英]Updating UI when a model property changes in an ObservableCollection?
我有一個視圖,我從一個Web服務獲得一組圖像,我在這個類的列表中收到它們:
public class ImageModel
{
public int Id { get; set; }
public string Name { get; set; }
public string imageUrl { get; set; }
}
在每個圖像下我顯示一個向上投票按鈕,所以我在上面的模型中添加了另一個bool屬性:
public bool UpVoted { get; set; }
顯示這些圖像的ListView
綁定到ObservableCollection<ImageModel >
,我想通過將UpVoted
的值轉換為相應圖標的轉換器更改投票圖標,當用戶單擊投票圖標時:命令執行此方法:
private void OnVoting(ImageModel image)
{
Images.Single(x => x.id == image.id).UpVoted = !image.UpVoted;
}
問題是UI沒有更新,為了確保我理解了問題,我將模型轉換為View模型,並對UpVoted
屬性進行了必要的更改(我使用的是MVVM光庫)
bool upVoted;
public bool UpVoted
{
get { return upVoted; }
set
{
Set(ref upVoted, value);
}
}
它現在可以工作,所以我需要將UpVoted
綁定到UI,因此只要它發生變化就會更新
首先,您的模型類必須從MvxNotifyPropertyChanged繼承
public class ImageModel : MvxNotifyPropertyChanged
{
public int Id { get; set; }
public string Name { get; set; }
private bool upVoted ;
public bool UpVoted
{
get { return upVoted ; }
set { upVoted = value; RaisePropertyChanged(() => UpVoted ); }
}
}
然后用MvxValueConverter
准備好了
Mustafa的回答提到了一個特定於MvvmCross庫的類。
另一種選擇是TinyMvvm
。
如果您希望編寫自己的MVVM(或了解MVVM如何工作),一般模式是實現INotifyPropertyChanged: 實現屬性更改通知 , 我在這里討論 。
實現INotifyPropertyChanged的一種便捷方法是創建一個執行該實現的基類,然后從該基類繼承。 您可以使用該示例中的代碼作為基類。 或者使用稍微不同的實現,避免必須手動將屬性名稱作為字符串傳遞:
using System.ComponentModel;
using System.Runtime.CompilerServices;
// Use this as base class for all your "view model" classes.
// And possibly for your (domain) model classes.
// E.g.: "public class MyLoginViewModel : HasNotifyPropertyChanged".
// OR "public class MyLoginModel : HasNotifyPropertyChanged".
// Give it whatever name you want, for ViewModels I suggest "ViewModelBase".
public class HasNotifyPropertyChanged : INotifyPropertyChanged
{
// --- This is pattern to use to implement each property. ---
// This works for any property type: int, Color, etc.
// What's different from a standard c# property, is the "SetProperty" call.
// You will often write an IValueConverter (elsewhere) to use in XAML to convert from string to your property type,
// or from your property type to a type needed in your UI.
// Comment out this example property if you don't need it.
/// <summary>
/// Set to "true" at end of your initialization.
/// Then can use Property Trigger on Ready value=true in XAML to do something when your instance is ready for use.
/// For example, load something from web, then trigger to update UI.
/// </summary>
private bool _ready;
public bool Ready
{
get => _ready;
set => SetProperty(ref _ready, value);
}
public event PropertyChangedEventHandler PropertyChanged;
protected void SetProperty<T>(ref T property, T value, [CallerMemberName] string propertyName = null)
{
if (property == null || !property.Equals(value))
{
property = value;
RaisePropertyChanged(propertyName);
}
}
protected void RaisePropertyChanged(string propertyName)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
同樣,上述代碼的替代方法是使用現有的MVVM庫。
對於另一種選擇, 這不需要在所有屬性設置器中寫入“SetProperty(..)”或“OnPropertyChanged(..)” ,谷歌有關使用Fody / PropertyChanged的信息 。 那你就不需要上面的代碼了; 你的類只會從INotifyPropertyChanged
繼承。 (在app啟動時,你調用一個方法,將所需的邏輯“注入”所有INotifyPropertyChanged類的所有屬性。)
致謝:上面示例中的代碼模式基於其中一個開源庫。 它可能來自TinyMvvm。
您沒有說明您正在使用哪種容器,但並非所有控件都設置為默認支持雙向通知。 所以你可能需要添加一個
Mode=TwoWay
從后端獲取數據已更改的通知。 或者,正如Mustafa先前的回答所示,您可能需要驗證您的班級是否正在使用mvvm light實現InotifyPropertyChanged事件。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.