[C#/SILVERLIGHT] Binding 태그 확장 : IDataErrorInfo 인터페이스를 이용한 바인딩 에러 처리하기
C#/Silverlight 2014. 2. 25. 23:42■ Binding 태그 확장 : IDataErrorInfo 인터페이스를 이용해 바인딩 에러 처리하기
------------------------------------------------------------------------------------------------------------------------
▶ Product.cs
using System; using System.Collections.Generic; using System.ComponentModel;
/// <summary> /// 제품 /// </summary> public class Product : IDataErrorInfo { //////////////////////////////////////////////////////////////////////////////////////////////////// Field ////////////////////////////////////////////////////////////////////////////////////////// Private
#region Field
/// <summary> /// 에러 사전 /// </summary> private Dictionary<string, List<string>> errorDictionary = new Dictionary<string, List<string>>();
/// <summary> /// ID 에러 메시지 /// </summary> private const string ID_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
// IDataErrorInfo #region 에러 - Error
/// <summary> /// 에러 /// </summary> public string Error { get { throw new NotImplementedException(); } }
#endregion
// IDataErrorInfo #region 인덱서 - this[propertyName]
/// <summary> /// 인덱서 /// </summary> /// <param name="propertyName">속성명</param> /// <returns>메시지</returns> public string this[string propertyName] { get { return (!this.errorDictionary.ContainsKey(propertyName) ? null : string.Join(Environment.NewLine, this.errorDictionary[propertyName])); } }
#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); } } }
#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); } } }
#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" /> <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" Margin="3" HorizontalAlignment="Right" 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, ValidatesOnDataErrors=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" Margin="3" HorizontalAlignment="Right" 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, ValidatesOnDataErrors=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.ColumnSpan="2" Margin="3" /> </Grid>
|
------------------------------------------------------------------------------------------------------------------------
※ ValidatesOnExceptions 속성을 설정하는 이유는 IDataErrorInfo 인터페이스에서 처리하는 무결성 조사 외에 예외가 발생하는 경우도 표시하기 위한 것이다.
※ NotifyOnValidationError 속성을 설정하는 이유는 ValidationSummary 엘리먼트에 에러 정보를 표시하기 위한 것이다.
'C# > Silverlight' 카테고리의 다른 글
[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 |
[C#/SILVERLIGHT] Binding 태그 확장 : Converter, ConverterParameter 속성 사용하기 (0) | 2014.02.25 |
댓글을 달아 주세요