所以我在视图模型上有一个ObservableCollection<Term>
,Term
个项目有一些数据属性。
Term
上课:
using SQLite;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace Neomilano.Model
{
public class Term
{
public int ID { get; set; }
public string Name { get; set; }
public DateTimeOffset TermStart { get; set; }
public DateTimeOffset TermEnd { get; set; }
public string DurationText
{
get
{
return "from " + TermStart.Date.ToString("MMMM d, yyyy") + " to " + TermEnd.Date.ToString("MMMM d, yyyy");
}
}
public Term()
{
}
}
}
这是有问题的ViewModel,它有ObservableCollection(ProjectBaseViewModel
实现了MVVM Light ViewModelBase
,而且我认为这里没有必要的属性:/ p>
using GalaSoft.MvvmLight.Command;
using GalaSoft.MvvmLight.Threading;
using Microsoft.Practices.ServiceLocation;
using Neomilano.Model;
using Neomilano.Services;
using SQLite;
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Input;
using Windows.Foundation;
namespace Neomilano.ViewModel
{
public partial class TermsViewModel : ProjectBaseViewModel
{
public IDialogService DialogService
{
get { return ServiceLocator.Current.GetInstance<IDialogService>(); }
}
#region properties
private ObservableCollection<Term> _terms;
public ObservableCollection<Term> Terms {
get { return this._terms; }
private set { Set(() => Terms, ref _terms, value); }
}
#endregion
#region commands
private RelayCommand<int> _deleteTermCommand;
public RelayCommand<int> DeleteTermCommand
{
get
{
return _deleteTermCommand ??
(_deleteTermCommand = new RelayCommand<int>(async id => {
var t = "Are you sure you want to delete this term?";
var c = "This cannot be undone.";
var ct = "delete";
bool deleteConfirmed = await DialogService.ShowConfirmationDialogAsync(t, c, ct);
if (deleteConfirmed == true)
await ExecuteDeleteTermAsync(id);
}));
}
}
#endregion
public TermsViewModel()
{
if (IsInDesignMode)
{
List<Term> t = new List<Term>();
t.Add(new Term() { ID=1, Name = "Sample Term 1", TermStart = DateTimeOffset.Parse("October 1, 2013"), TermEnd = DateTimeOffset.Parse("December 17, 2013") });
t.Add(new Term() { ID=2, Name="Sample Term 2", TermStart=DateTimeOffset.Parse("January 1, 2014"), TermEnd=DateTimeOffset.Parse("April 30, 2014") });
Terms = new ObservableCollection<Term>(t);
}
}
/// <summary>
/// Gets the list of Terms from the database and adds it to the Terms property of the ViewModel.
/// </summary>
/// <returns></returns>
public async Task GetTermsListAsync()
{
IsProgressEnabled = true;
List<Term> list = new List<Term>();
await Task.Run(() =>
{
using (var db = new SQLiteConnection(app.DBFileName))
{
list = db.Table<Term>().ToList<Term>();
db.Close();
}
});
Terms = new ObservableCollection<Term>(list);
IsProgressEnabled = false;
}
/// <summary>
/// Returns the term ID of the selected term from the view.
/// </summary>
/// <param name="clickedItem"></param>
/// <returns></returns>
public Term ReturnSelectedTerm(object clickedItem)
{
return (Term)clickedItem;
}
public async Task ExecuteDeleteTermAsync(int termId)
{
IsProgressEnabled = true;
Term t = new Term();
await Task.Run(() =>
{
using (var db = new SQLiteConnection(app.DBFileName))
{
var q = db.Table<Term>().Where(tr => tr.ID.Equals(termId));
t = q.First<Term>();
db.Delete<Term>(termId);
db.Close();
}
});
var target = Terms.Single<Term>(tr => tr.ID.Equals(termId));
Terms.Remove(target);
IsProgressEnabled = false;
}
}
}
问题:当然,在其他网页上添加和删除字词效果很好。但是,当Term
项目更新时,只会更新标题。
以下是视图中的内容:
<ListView
x:Name="TermsListView"
ItemsSource="{Binding Terms}"
IsItemClickEnabled="True"
ItemClick="OnTermItemClick">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Holding="OnTermItemHold">
<FlyoutBase.AttachedFlyout>
<MenuFlyout x:Name="TermItemContextMenu">
<MenuFlyoutItem Text="edit" Command="{Binding TermsViewModel.NavigateToFormCommand, Mode=OneWay, Source={StaticResource Locator}}" CommandParameter="{Binding}" />
<MenuFlyoutItem Text="delete" Command="{Binding TermsViewModel.DeleteTermCommand, Mode=OneWay, Source={StaticResource Locator}}" CommandParameter="{Binding ID}" />
</MenuFlyout>
</FlyoutBase.AttachedFlyout>
<TextBlock Text="{Binding Name}" Style="{ThemeResource ListViewItemTextBlockStyle}"/>
<TextBlock Text="{Binding DurationText}" Style="{ThemeResource ListViewItemSubheaderTextBlockStyle}"/>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
两个日期值发生更改时, Term.DurationText
不会更新。但是,如果要查看编辑页面,则更改将反映在DatePickers中。
有没有什么方法可以让DurationText
相应地通过Binding更新它与使用 MVVM Light 的实现一起工作?
I have tried this但错误说:
类型&#39; Neomilano.Model.Term&#39;不能用作类型参数&#39; T&#39; 在泛型类型或方法中 &#39; Neomilano.Common.ItemsChangeObservableCollection&#39 ;.没有 来自Neomilano.Model.Term&#39;的隐式参考转换至 &#39; System.ComponentModel.INotifyPropertyChanged&#39;
项目规格: *这是一个WinRT应用程序 *它是一个通用的Windows应用程序,但我现在首先在Windows Phone上工作。我认为这并不重要,因为收敛赌注。 WinRT和WinPRT,但谁知道这可能是问题所在 *正如我所提到的,我使用MVVM Light(仅限库)。
所以,一般来说,如何使用MVVM Light 更新WinRT中ObservableCollection项的内容?
感谢您的帮助!
答案 0 :(得分:3)
您在链接文章中不需要任何内容,只需要Term
来强制INotifyPropertyChanged
。 ObservableCollection<T>
仅通知与其绑定的ListView
该集合的内容已更改,即它通知添加,删除,移动,替换,重置等。它没有&#39} ; t监视集合中的项目是否有变化。
在这种情况下,您可以Term
派生ViewModelBase
,因为它包含INotifyPropertyChanged
的实现。
以下是一个例子。请注意TermStart
的setter如何为DurationText
引发更改事件,因为此属性是依赖的。
public class Term : ViewModelBase
{
private int _id;
private string _name;
private DateTimeOffset _termStart;
private DateTimeOffset _termEnd;
public int Id
{
get { return _id; }
set
{
if (value == _id) return;
_id = value;
RaisePropertyChanged("Id");
}
}
public string Name
{
get { return _name; }
set
{
if (value == _name) return;
_name = value;
RaisePropertyChanged("Name");
}
}
public DateTimeOffset TermStart
{
get { return _termStart; }
set
{
if (value.Equals(_termStart)) return;
_termStart = value;
RaisePropertyChanged("TermStart");
RaisePropertyChanged("DurationText");
}
}
public DateTimeOffset TermEnd
{
get { return _termEnd; }
set
{
if (value.Equals(_termEnd)) return;
_termEnd = value;
RaisePropertyChanged("TermEnd");
RaisePropertyChanged("DurationText");
}
}
public string DurationText
{
get { return "from " + TermStart.Date.ToString("MMMM d, yyyy") + " to " + TermEnd.Date.ToString("MMMM d, yyyy"); }
}
}