[英]IDataErrorInfo error messagebox on save button click
我正在構建一個wpf應用程序,並且在類中實現了IDataErrorInfo
接口。 一切正常, textbox
已正確綁定,帶有錯誤消息的工具提示正確顯示,並且屬性更改時邊框變為紅色。
但是,當我單擊“保存”按鈕(創建我的實體並將其保存到數據庫中)時,即使文本框中的值錯誤,也會將錯誤的值保存在數據庫中。
過去,我在屬性設置器中使用過ArgumentException
,然后單擊“保存”按鈕時,在try / catch內顯示了一個帶有錯誤消息的消息框,但未保存我的錯誤值。
有沒有類似的方法來實現消息框,例如try / catch一個,但使用IDataErrorInfo
?
我不是在尋找復雜的解決方案,因為我是一個初學者,這是我第一次嘗試使用IDataErrorInfo 。
由於有評論,我將答案更新為更詳細的答案。
首先, Newspeak是Ingsoc,而Ingsoc是Newspeak, XAML是MVVM,而MVVM是XAML。
要編寫與“ Hello,world”截然不同的內容,您必須特別學習MVVM和命令。 下面的代碼使用以下ICommand
實現:
public sealed class RelayCommand : ICommand
{
private readonly Action execute;
private readonly Func<bool> canExecute;
public RelayCommand(Action execute, Func<bool> canExecute)
{
this.execute = execute;
this.canExecute = canExecute;
}
public event EventHandler CanExecuteChanged
{
add { CommandManager.RequerySuggested += value; }
remove { CommandManager.RequerySuggested -= value; }
}
public bool CanExecute(object parameter)
{
return canExecute();
}
public void Execute(object parameter)
{
execute();
}
}
在現實世界的應用程序中,WPF驗證使用一些知名的驗證框架卧底,並且幾乎永遠不會在需要驗證的每個視圖模型中手動實現。
這是在IDataErrorInfo
驗證的示例,該驗證在基類中使用數據批注實現 :
public abstract class ViewModel : INotifyPropertyChanged, IDataErrorInfo
{
public event PropertyChangedEventHandler PropertyChanged;
protected virtual void OnPropertyChanged([CallerMemberName]string propertyName = null)
{
// updating property-bound controls
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
// updating command-bound controls like buttons
CommandManager.InvalidateRequerySuggested();
}
private readonly ObservableCollection<ViewModelError> validationErrors = new ObservableCollection<ViewModelError>();
private void RemoveValidationErrors(string propertyName)
{
var propertyValidationErrors = validationErrors
.Where(_ => _.PropertyName == propertyName)
.ToArray();
foreach (var error in propertyValidationErrors)
{
validationErrors.Remove(error);
}
}
private string ValidateProperty(string propertyName)
{
// we need localized property name
var property = GetType().GetProperty(propertyName);
var displayAttribute = property.GetCustomAttribute<DisplayAttribute>();
var propertyDisplayName = displayAttribute != null ? displayAttribute.GetName() : propertyName;
// since validation engine run all validation rules for property,
// we need to remove validation errors from the previous validation attempt
RemoveValidationErrors(propertyDisplayName);
// preparing validation engine
var validationContext = new ValidationContext(this, null, null) { MemberName = propertyName };
var validationResults = new List<ValidationResult>();
// running validation
if (!Validator.TryValidateProperty(property.GetValue(this), validationContext, validationResults))
{
// validation is failed;
// since there could be several validation rules per property,
// validation results can contain more than single error
foreach (var result in validationResults)
{
validationErrors.Add(new ViewModelError(propertyDisplayName, result.ErrorMessage));
}
// to indicate validation error, it's enough to return first validation message
return validationResults[0].ErrorMessage;
}
return null;
}
public IEnumerable<ViewModelError> ValidationErrors
{
get { return validationErrors; }
}
public string this[string columnName]
{
get { return ValidateProperty(columnName); }
}
public string Error
{
get { return null; }
}
}
ViewModelError
只是一個容器:
public sealed class ViewModelError
{
public ViewModelError(string propertyName, string errorMessage)
{
PropertyName = propertyName;
ErrorMessage = errorMessage;
}
public string PropertyName { get; private set; }
public string ErrorMessage { get; private set; }
}
讓我們看一下表示一些人數據的模型,相應的視圖模型和視圖:
一個模型
public class Person
{
public Guid Id { get; set; }
public string Name { get; set; }
public int Age { get; set; }
}
b)視圖模型
public class PersonViewModel : ViewModel
{
private void HandleSave()
{
var person = new Person
{
Id = Guid.NewGuid(),
Name = Name,
Age = Age
};
// save person using database, web service, file...
}
private bool CanSave()
{
return !ValidationErrors.Any();
}
public PersonViewModel()
{
SaveCommand = new RelayCommand(HandleSave, CanSave);
}
[Display(Name = "Full name of person")]
[Required(AllowEmptyStrings = false)]
[MaxLength(50)]
public string Name
{
get { return name; }
set
{
if (name != value)
{
name = value;
OnPropertyChanged();
}
}
}
private string name;
[Display(Name = "Age of person")]
[Range(18, 65)]
public int Age
{
get { return age; }
set
{
if (age != value)
{
age = value;
OnPropertyChanged();
}
}
}
private int age;
public ICommand SaveCommand { get; private set; }
}
c)視圖(WPF窗口)
<Window x:Class="Wpf_IDataErrorInfoSample.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:Wpf_IDataErrorInfoSample"
mc:Ignorable="d"
Title="MainWindow" Height="300" Width="400">
<Window.DataContext>
<local:PersonViewModel />
</Window.DataContext>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="Auto"/>
</Grid.RowDefinitions>
<!-- Validation summary -->
<ItemsControl ItemsSource="{Binding ValidationErrors}">
<ItemsControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:ViewModelError}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding PropertyName}"/>
<TextBlock Text=" : "/>
<TextBlock Text="{Binding ErrorMessage}"/>
</StackPanel>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<!-- Editable fields -->
<StackPanel Grid.Row="1" Margin="4, 10, 4, 4">
<!-- Name -->
<TextBlock Text="Name:"/>
<TextBox Text="{Binding Name, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True}"/>
<!-- Age -->
<TextBlock Text="Age:"/>
<Slider Minimum="0" Maximum="120" TickPlacement="BottomRight" Value="{Binding Age, ValidatesOnDataErrors=True}"/>
</StackPanel>
<Button Grid.Row="2" Content="Save" Command="{Binding SaveCommand}"/>
</Grid>
</Window>
如果運行此代碼,則初始圖片如下所示:
如您所見,如果存在驗證錯誤,該按鈕將被禁用,並且您將無法保存無效數據。 如果您要糾正錯誤,則該按鈕將變為啟用狀態,您可以單擊它來保存數據:
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.