我有这段代码:
wordGrid.BindingContext = AS.phrase;
AS.phrase = new PSCViewModel() { English = "abcd" };
AS.phrase.English = "JJJJ";
在第一行设置BindingContext时,我在视图中看不到任何内容。有了它,它可以工作,我看到" JJJJ"。
这是我的viewModel:
public class PSCViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
int id;
string english;
public PSCViewModel()
{
}
public int Id
{
get { return id; }
set
{
if (value != id)
{
id = value;
onPropertyChanged("ID");
}
}
}
public string English
{
get { return english; }
set
{
if (value != english)
{
english = value;
onPropertyChanged("English");
}
}
}
private void onPropertyChanged(string v)
{
if (PropertyChanged != null)
{
PropertyChanged(this,
new PropertyChangedEventArgs(v));
}
}
}
有人能看出为什么对英文字段的更改不会导致显示JJJJ的新值吗?
答案 0 :(得分:1)
一个好的开始是阅读MVVM模式以及如何在Xamarin Forms中实现它。 Xamarin有关于这个主题的自己的教程:
https://developer.xamarin.com/guides/xamarin-forms/xaml/xaml-basics/data_bindings_to_mvvm/
基本上你要做的是创建一个ViewModel,它充当整个页面的BindingContext
。在该ViewModel中,您可以定义绑定到控件的属性,例如Labels
,ListViews
和TextBoxes
。在您的情况下,ViewModel将包含一个名为Phrase的string
属性,该属性绑定到名为wordGrid
的控件。
public class PhraseViewModel
{
public string Phrase {get; set;}
}
可以在XAML中绑定到例如标签如:
<Label Text="{Binding Phrase}" />
答案 1 :(得分:1)
您可能已在System.ComponentModel
这是MVVM的全部内容。您的ViewModel必须实现INotifyPropertyChanged
。其中只有一个事件:PropertyChangedEventHandler PropertyChanged
我通常在ViewModel中定义一个raise方法,如下所示:
protected void RaisePropertyChanged(string propertyName = "")
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
然后,ViewModel中的所有属性都必须具有这样的getter / setter:
public string AProperty
{
get { return aProperty;}
set
{
if(value != aProperty)
{
aProperty = value;
RaisePropertyChanged("AProperty");
}
}
}
现在,当您将View与ViewModel绑定时,它将订阅PropertyChanged事件并传播更改。就是这样!
答案 2 :(得分:1)
这就是我实现INotifyPropertyChanged的方式。
public class Bindable : INotifyPropertyChanged
{
private Dictionary<string, object> _properties = new Dictionary<string, object>();
/// <summary>
/// Gets the value of a property
/// <typeparam name="T"></typeparam>
/// <param name="name"></param>
/// <returns></returns>
protected T Get<T>([CallerMemberName] string name = null)
{
object value = null;
if (_properties.TryGetValue(name, out value))
return value == null ? default(T) : (T)value;
return default(T);
}
/// <summary>
/// Sets the value of a property
/// </summary>
/// <typeparam name="T"></typeparam>
/// <param name="value"></param>
/// <param name="name"></param>
protected void Set<T>(T value, [CallerMemberName] string name = null)
{
if (Equals(value, Get<T>(name)))
return;
_properties[name] = value;
OnPropertyChanged(name);
}
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
这是一个描述如何使用
的示例类 public class Transaction : Bindable
{
public Transaction()
{
this.TransactionDate = DateTimeOffset.Now;
this.TransactionType = TransactionType.Add; //enum
this.Quantity = 0;
this.IsDeleted = false;
this.Item = null; //object defined elsewhere
}
public Guid Id { get { return Get<Guid>(); } private set { Set<Guid>(value); } }
public DateTimeOffset? TransactionDate { get { return Get<DateTimeOffset?>(); } set { Set<DateTimeOffset?>(value); } }
public TransactionType TransactionType { get { return Get<TransactionType>(); } set { Set<TransactionType>(value); } }
public double? Quantity { get { return Get<double?>(); } set { Set<double?>(value); } }
public bool? IsDeleted { get { return Get<bool?>(); } set { Set<bool?>(value); } }
public byte[] RowVersion { get { return Get<byte[]>(); } private set { Set<byte[]>(value); } }
public virtual Guid? ItemId { get { return Get<Guid?>(); } set { Set<Guid?>(value); } }
public virtual Item Item { get { return Get<Item>(); } set { Set<Item>(value); } }
}