我为你构建了一个简单的TestClass:
以下课程:
failure
我将这些数据存储在public abstract class Person : INotifyPropertyChanged
public class Adult : Person
public class Child : Person
中,并希望在我的窗口中显示:
ObservableCollection<Person>
我在<ListView ItemsSource="{Binding People}" SelectedItem="{Binding SelectedPerson}" Grid.Column="0">
<ListView.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock>
<Run Text="{Binding FirstName}"/>
<Run Text="{Binding LastName}"/>
</TextBlock>
</StackPanel>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
中显示的所选内容:
ContentPresenter
现在任何人都可以告诉我如何取消我的编辑(CancelCommand)或以正确的MVVM方式保存它们(SaveCommand)。
现在,当TextBox丢失焦点时,我的程序会保存它们,并且它们无法撤消。
有人可以给我发一个例子吗?
此外,我不知道我的输入无效: 我尝试过:
<ContentPresenter Content="{Binding SelectedPerson}">
<ContentPresenter.Resources>
<DataTemplate DataType="{x:Type local:Adult}">
<StackPanel>
<TextBlock Text="First Name:"/>
<TextBox>
<TextBox.Text>
<Binding Path="FirstName">
<Binding.ValidationRules>
<local:NotEmptyRule/>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
</TextBox>
<TextBlock Text="Last Name:"/>
<TextBox Text="{Binding LastName}"/> <!-- Validation same as FirstName -->
<TextBlock Text="Company:"/>
<TextBox Text="{Binding Company}"/>
</StackPanel>
</DataTemplate>
<DataTemplate DataType="{x:Type local:Child}">
<StackPanel>
<TextBlock Text="First Name:"/>
<TextBox Text="{Binding FirstName}"/> <!-- Validation same as above-->
<TextBlock Text="Last Name:"/>
<TextBox Text="{Binding LastName}"/> <!-- Validation same as above-->
<TextBlock Text="School:"/>
<TextBox Text="{Binding School}"/>
</StackPanel>
</DataTemplate>
</ContentPresenter.Resources>
</ContentPresenter>
但即使我的TextBox显示错误,我的函数也告诉我该条目有效。
感谢您帮助我!
答案 0 :(得分:1)
如果您需要验证,则需要在实体上实施INotifyDataErrorInfo
。如果要还原更改,则需要实现IRevertibleChangeTracking
。如果你以前从未做过这两件事,那么这两件事都不容易。
还有另一种解决接受/取消问题的方法。当您开始编辑Person
时,将所有数据复制到PersonViewModel
。然后,您将数据绑定到PersonViewModel
,当用户点击保存时,将数据复制回Person
,当用户点击取消时,只需忽略更改。
PersonViewModel
类不是必需的,您可以创建新的实例Person
,但PersonViewModel
为您提供了更多的UI逻辑灵活性。例如,您可以在表示层使用密码和重复密码字段,但在业务实体中只需要密码。
答案 1 :(得分:0)
我撤消更改的解决方案:
public abstract class Person : INotifyPropertyChanged, ICloneable, IEditableObject
已实施接口成员:
Person _Backup = null;
public object Clone()
{
return MemberwiseClone();
}
public void BeginEdit()
{
_Backup = Clone() as Person;
HasChanges = false;
}
public void CancelEdit()
{
foreach (var Prop in GetType().GetProperties())
{
Prop.SetValue(this, Prop.GetValue(_Backup));
}
HasChanges = false;
}
public void EndEdit()
{
_Backup = null;
HasChanges = false;
}
在ViewModel中:
private const string SelectedPersonPropertyName = "SelectedPerson";
private Person _SelectedPerson;
public Person SelectedPerson
{
get
{
return _SelectedPerson;
}
set
{
if (_SelectedPerson != null)
{
_SelectedPerson.EndEdit();
}
if (value != null)
{
value.BeginEdit();
}
_SelectedPerson = value;
RaisePropertyChanged(SelectedPersonPropertyName);
}
}
实现我的验证规则:
private const string FirstNamePropertyName = "FirstName";
private string _FirstName;
public string FirstName
{
get
{
return _FirstName;
}
set
{
if (_FirstName == value)
return;
ValidationResult _Result = _NotEmptyRule.Validate(value, System.Globalization.CultureInfo.CurrentCulture);
if (!_Result.IsValid)
{
AddError(FirstNamePropertyName, ValueIsNullOrBlank);
}
else
{
RemoveError(FirstNamePropertyName, ValueIsNullOrBlank);
}
_FirstName = value;
HasChanges = true;
RaisePropertyChanged(FirstNamePropertyName);
}
}
private const string ValueIsNullOrBlank = "ValueIsNullOrBlank";
private NotEmptyRule _NotEmptyRule = new NotEmptyRule();
private Dictionary<string, List<object>> _Errors = new Dictionary<string, List<object>>();
protected void AddError(string PropertyName, object Error)
{
if (!_Errors.ContainsKey(PropertyName))
{
_Errors[PropertyName] = new List<object>();
}
if (!_Errors[PropertyName].Contains(Error))
{
_Errors[PropertyName].Add(Error);
RaiseErrorsChanged(PropertyName);
}
}
protected void RemoveError(string PropertyName, object Error)
{
if (_Errors.ContainsKey(PropertyName) && _Errors[PropertyName].Contains(Error))
{
_Errors[PropertyName].Remove(Error);
if (_Errors[PropertyName].Count == 0)
{
_Errors.Remove(PropertyName);
}
RaiseErrorsChanged(PropertyName);
}
}
public void RaiseErrorsChanged(string PropertyName)
{
if (ErrorsChanged != null)
ErrorsChanged(this, new DataErrorsChangedEventArgs(PropertyName));
}
public IEnumerable GetErrors(string PropertyName)
{
if (String.IsNullOrEmpty(PropertyName) ||
!_Errors.ContainsKey(PropertyName)) return null;
return _Errors[PropertyName];
}
public bool HasErrors
{
get { return _Errors.Count > 0; }
}
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
private const string HasChangesPropertyName = "HasChanges";
private bool _HasChanges;
public bool HasChanges
{
get
{
return _HasChanges;
}
set
{
_HasChanges = value;
RaisePropertyChanged(HasChangesPropertyName);
}
}
我遇到的唯一问题是:我没有克隆我的私人信息(只是我的属性)有没有人知道这里的帮助?