【发布时间】:2016-09-12 00:45:27
【问题描述】:
我使用以下新的 BindableViewModel 类(旧的我也在本主题的底部发布)使对象可观察(来自 MS 示例):
public abstract class BindableBase : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged = delegate { };
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propertyName = null)
{
if (object.Equals(storage, value)) return false;
storage = value;
this.OnPropertyChanged(propertyName);
return true;
}
protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
我想用它来创建一个 ViewModel 来绑定那些 TextBox 控件,例如:
public class TextBoxModel : BindableBase
{
private string _text = string.Empty;
// I'm going to bind this field to TextBox.Text property
public string Text { get { return _text; } set { SetProperty(ref _text, value); } }
private bool _isEnabled = true;
// I'm going to bind this field to TextBox.IsEnabled property
public bool IsEnabled { get { return _isEnabled; } set { SetProperty(ref _isEnabled, value); } }
}
然后,在我的 Page ViewModel 中,我使用 TextBoxModel 来定义字段:
public class Page1ViewModel : BindableBase
{
private TextBoxModel _firstName = null;
public TextBoxModel FirstName { get { return _firstName; } set {
if (SetProperty(ref _firstName, value))
{
SubmitCommand.RaiseCanExecuteChanged();
} } }
private TextBoxModel _surname = null;
public TextBoxModel Surname { get { return _surname; } set {
if (SetProperty(ref _surname, value))
{
SubmitCommand.RaiseCanExecuteChanged();
} } }
private DelegateCommand _submitCommand = null;
public DelegateCommand SubmitCommand { get { return _submitCommand??(_submitCommand=new DelegateCommand(SubmitExecute, SubmitCanExecute)); } }
private void SubmitExecute()
{
MessageBox.Show($"{FirstName.Text} {Surname.Text}");
}
private bool SubmitCanExecute()
{
if(string.IsNullOrEmpty(FirstName.Text))
return false;
else if(string.IsNullOrEmpty(Surname.Text))
return false;
else
return true;
}
}
在我的 XAML 视图中,我像往常一样设置文本框绑定:
<TextBox Text="{Binding FirstName.Text, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding FirstName.IsEnabled}"/>
<TextBox Text="{Binding Surname.Text, UpdateSourceTrigger=PropertyChanged}" IsEnabled="{Binding Surname.IsEnabled}"/>
<Button Content="Submit" Command{Binding SubmitCommand} />
当我运行它时,我发现文本更改不起作用。它没有在 setter 中触发 if(SetProperty(ref _firstName, value)) 或 if(SetProperty(ref _surname, value)) 。如果我不结合 TextBoxModel 中的属性,一切正常。如果我使用 OLD ViewModelBase,TextBoxModel 也可以正常工作。
所以我认为在使用新的 BindableBase 类时我一定错过了什么?寻求您的帮助,谢谢!
旧视图模型库:
[Obsolete("Please use BindableBase。")]
public abstract class ObservableModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public static string GetPropertyName<T>(System.Linq.Expressions.Expression<Func<T>> e)
{
var member = (System.Linq.Expressions.MemberExpression)e.Body;
return member.Member.Name;
}
protected virtual void RaisePropertyChanged<T>
(System.Linq.Expressions.Expression<Func<T>> propertyExpression)
{
RaisePropertyChanged(GetPropertyName(propertyExpression));
}
protected void RaisePropertyChanged(String propertyName)
{
System.ComponentModel.PropertyChangedEventHandler temp = PropertyChanged;
if (temp != null)
{
temp(this, new System.ComponentModel.PropertyChangedEventArgs(propertyName));
}
}
}
【问题讨论】:
-
我不明白这是怎么工作的。当文本更改时(或者,实际上,根本没有!),您没有设置
FirstName或Surname,因此不会调用SetProperty。您需要观察 withinTextBoxModel. 的属性变化 -
@CharlesMager 你是什么意思?我确实更改了 FirstName 对象的 Text 属性,但它没有触发 if(SetProperty(ref _firstName, value))。但是,它触发了 FirstName 对象内的 Text 属性。为什么 if(SetProperty(ref _firstName, value)) 甚至里面的 Text 属性都没有触发?
-
您的绑定是到
Text属性,即string。尝试设置该值不会神奇地新建TextBoxModel并设置FirstName。它只会默默地失败,因为FirstName是null。