[C#/SILVERLIGHT] Binding 태그 확장 : INotifyDataErrorInfo 인터페이스를 이용한 바인딩 에러 처리하기
C#/Silverlight 2014. 2. 26. 02:56■ Binding 태그 확장 : INotifyDataErrorInfo 인터페이스를 이용해 바인딩 에러 처리하기
------------------------------------------------------------------------------------------------------------------------
▶ Product.cs
using System; using System.Collections; using System.Collections.Generic; using System.ComponentModel;
/// <summary> /// 제품 /// </summary> public class Product : INotifyDataErrorInfo { //////////////////////////////////////////////////////////////////////////////////////////////////// Event ////////////////////////////////////////////////////////////////////////////////////////// Public
// INotifyDataErrorInfo #region 에러 변경시 - ErrorsChanged
/// <summary> /// 에러 변경시 /// </summary> public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary> /// 에러 사전 /// </summary> private Dictionary<string, List<string>> errorDictionary = new Dictionary<string, List<string>>();
/// <summary> /// ID 에러 메시지 /// </summary> private const string ERROR_MESSAGE = "Value cannot be less than 5.";
/// <summary> /// ID 경고 메시지 /// </summary> private const string ID_WARNING_MESSAGE = "Value should not be less than 10.";
/// <summary> /// 명칭 에러 메시지 /// </summary> private const string NAME_ERROR_MESSAGE = "Value must not contain any spaces.";
/// <summary> /// 명칭 경고 메시지 /// </summary> private const string NAME_WARNING_MESSAGE = "Value should be 5 characters or less.";
/// <summary> /// ID /// </summary> private int id;
/// <summary> /// 명칭 /// </summary> private string name;
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Property ////////////////////////////////////////////////////////////////////////////////////////// Public
// INotifyDataErrorInfo #region 에러 여부 - HasErrors
/// <summary> /// 에러 여부 /// </summary> public bool HasErrors { get { return this.errorDictionary.Count > 0; } }
#endregion
#region ID - ID
/// <summary> /// ID /// </summary> public int ID { get { return this.id; } set { if(IsIDValid(value) && this.id != value) { this.id = value; } } }
#endregion
#region 명칭 - Name
/// <summary> /// 명칭 /// </summary> public string Name { get { return this.name; } set { if(IsNameValid(value) && this.name != value) { this.name = value; } } }
#endregion
//////////////////////////////////////////////////////////////////////////////////////////////////// Method ////////////////////////////////////////////////////////////////////////////////////////// Public
#region ID 무결성 여부 조사하기 - IsIDValid(id)
/// <summary> /// ID 무결성 여부 조사하기 /// </summary> /// <param name="id">ID</param> /// <returns>ID 무결성 여부</returns> public bool IsIDValid(int id) { bool isValid = true;
if(id < 5) { AddError("ID", ID_ERROR_MESSAGE, false);
isValid = false; } else { RemoveError("ID", ID_ERROR_MESSAGE); }
if(id< 10) { AddError("ID", ID_WARNING_MESSAGE, true); } else { RemoveError("ID", ID_WARNING_MESSAGE); }
return isValid; }
#endregion
#region 명칭 무결성 여부 조사하기 - IsNameValid(name)
/// <summary> /// 명칭 무결성 여부 조사하기 /// </summary> /// <param name="name">명칭</param> /// <returns>명칭 무결성 여부</returns> public bool IsNameValid(string name) { bool isValid = true;
if(name.Contains(" ")) { AddError("Name", NAME_ERROR_MESSAGE, false);
isValid = false; } else { RemoveError("Name", NAME_ERROR_MESSAGE); }
if(name.Length > 5) { AddError("Name", NAME_WARNING_MESSAGE, true); } else { RemoveError("Name", NAME_WARNING_MESSAGE); }
return isValid; }
#endregion
#region 에러 추가하기 - AddError(propertyName, message, isWarning)
/// <summary> /// 에러 추가하기 /// </summary> /// <param name="propertyName">속성명</param> /// <param name="message">메시지</param> /// <param name="isWarning">경고 여부</param> public void AddError(string propertyName, string message, bool isWarning) { if(!this.errorDictionary.ContainsKey(propertyName)) { this.errorDictionary[propertyName] = new List<string>(); }
if(!this.errorDictionary[propertyName].Contains(message)) { if(isWarning) { this.errorDictionary[propertyName].Add(message); } else { this.errorDictionary[propertyName].Insert(0, message); }
RaiseErrorsChanged(propertyName); } }
#endregion
#region 에러 제거하기 - RemoveError(propertyName, message)
/// <summary> /// 에러 제거하기 /// </summary> /// <param name="propertyName">속성명</param> /// <param name="message">메시지</param> public void RemoveError(string propertyName, string message) { if(this.errorDictionary.ContainsKey(propertyName) && this.errorDictionary[propertyName].Contains(message)) { this.errorDictionary[propertyName].Remove(message);
if(this.errorDictionary[propertyName].Count == 0) { this.errorDictionary.Remove(propertyName); }
RaiseErrorsChanged(propertyName); } }
#endregion
#region ErrorsChanged 이벤트 발생시키기 - RaiseErrorsChanged(propertyName)
/// <summary> /// ErrorsChanged 이벤트 발생시키기 /// </summary> /// <param name="propertyName">속성명</param> public void RaiseErrorsChanged(string propertyName) { if(ErrorsChanged != null) { ErrorsChanged(this, new DataErrorsChangedEventArgs(propertyName)); } }
#endregion
// INotifyDataErrorInfo #region 에러 조사하기 - GetErrors(propertyName)
/// <summary> /// 에러 조사하기 /// </summary> /// <param name="propertyName">속성명</param> /// <returns>에러 리스트</returns> public IEnumerable GetErrors(string propertyName) { if(string.IsNullOrEmpty(propertyName) || !this.errorDictionary.ContainsKey(propertyName)) { return null; }
return this.errorDictionary[propertyName]; }
#endregion }
|
▶ MainPage.xaml.cs
using System.Windows.Controls; using System.Windows.Input;
...
#region 생성자 - MainPage()
/// <summary> /// 생성자 /// </summary> public MainPage() { InitializeComponent();
this.grid.DataContext = new Product() { ID = 10, Name = "food" }; }
#endregion
...
#region 텍스트 박스 키 다운시 처리하기 - TextBox_KeyDown(sender, e)
/// <summary> /// 텍스트 박스 키 다운시 처리하기 /// </summary> /// <param name="sender">이벤트 발생자</param> /// <param name="e">이벤트 인자</param> private void TextBox_KeyDown(object sender, KeyEventArgs e) { if(e.Key == Key.Enter) { (sender as TextBox).GetBindingExpression(TextBox.TextProperty).UpdateSource(); } }
#endregion
|
▶ MainPage.xaml
<Grid x:Name="grid" xmlns:input="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data.Input" Margin="10" Background="White"> <Grid.RowDefinitions> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> <RowDefinition Height="Auto" /> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto" /> <ColumnDefinition Width="200" /> <ColumnDefinition Width="Auto" /> </Grid.ColumnDefinitions> <TextBlock Grid.Row="0" Grid.Column="1" Margin="3" FontWeight="Bold" Text="Product" /> <input:Label Grid.Row="1" Grid.Column="0" HorizontalAlignment="Right" Margin="3" Target="{Binding ElementName=idTextBox}" /> <TextBox x:Name="idTextBox" Grid.Row="1" Grid.Column="1" Margin="3" MaxLength="5" Text="{Binding ID, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}" KeyDown="TextBox_KeyDown" /> <input:DescriptionViewer Grid.Row="1" Grid.Column="2" Description="ID must be greater than 4 and should be greater than 9." /> <input:Label Grid.Row="2" Grid.Column="0" HorizontalAlignment="Right" Margin="3" Target="{Binding ElementName=nameTextBox}" /> <TextBox x:Name="nameTextBox" Grid.Row="2" Grid.Column="1" Margin="3" MaxLength="10" Text="{Binding Name, Mode=TwoWay, ValidatesOnExceptions=True, NotifyOnValidationError=True}" KeyDown="TextBox_KeyDown" /> <input:DescriptionViewer Grid.Row="2" Grid.Column="2" Description="Name must not contain spaces and should be 5 characters or less." /> <input:ValidationSummary Grid.Row="3" Grid.Column="0" Grid.ColumnSpan="2" Margin="3" /> </Grid>
|
------------------------------------------------------------------------------------------------------------------------
※ ValidatesOnExceptions 속성을 설정하는 이유는 INotifyDataErrorInfo 인터페이스에서 처리하는 무결성 조사 외에 예외가 발생하는 경우도 표시하기 위한 것이다.
※ INotifyDataErrorInfo 인터페이스를 처리하기 위해 ValidatesOnNotifyDataErrors 속성을 True로 설정해야 하는데 디폴트 값이 True이기 때문에 명시하지 않은 것이다.
※ NotifyOnValidationError 속성을 설정하는 이유는 ValidationSummary 엘리먼트에 에러 정보를 표시하기 위한 것이다.
'C# > Silverlight' 카테고리의 다른 글
[C#/SILVERLIGHT] ItemsPanelTemplate 엘리먼트 사용하기 (0) | 2014.02.26 |
---|---|
[C#/SILVERLIGHT] VisualStateManager 엘리먼트 사용하기 (0) | 2014.02.26 |
[C#/SILVERLIGHT] ResourceDictionary 엘리먼트 : MergedDictionaries 속성을 사용해 리소스 파일 병합하기 (0) | 2014.02.26 |
[C#/SILVERLIGHT] 리소스 구하기 (0) | 2014.02.26 |
[C#/SILVERLIGHT] Binding 태그 확장 : NotifyOnValidationError 속성과 BindingValidationError 이벤트 사용하기 (0) | 2014.02.26 |
[C#/SILVERLIGHT] Binding 태그 확장 : INotifyDataErrorInfo 인터페이스를 이용한 바인딩 에러 처리하기 (0) | 2014.02.26 |
[C#/SILVERLIGHT] Binding 태그 확장 : IDataErrorInfo 인터페이스를 이용한 바인딩 에러 처리하기 (0) | 2014.02.25 |
[C#/SILVERLIGHT] Binding 태그 확장 : Exception 객체를 이용한 바인딩 에러 처리하기 (0) | 2014.02.25 |
[C#/SILVERLIGHT] Binding 태그 확장 : FallbackValue 속성 사용하기 (0) | 2014.02.25 |
[C#/SILVERLIGHT] Binding 태그 확장 : TargetNullValue 속성 사용하기 (0) | 2014.02.25 |
[C#/SILVERLIGHT] Binding 태그 확장 : StringFormat 속성 사용하기 (0) | 2014.02.25 |
댓글을 달아 주세요