WPF에서 바인드된 컨트롤에 대한 강제 유효성 검사
텍스트 상자 몇 개가 있는 WPF 대화 상자가 있습니다.텍스트 상자는 비즈니스 개체에 바인딩되어 있으며 WPF 유효성 검사 규칙이 연결되어 있습니다.
문제는 사용자가 실제로 텍스트 상자에 데이터를 입력하지 않고도 '확인' 버튼을 클릭하고 대화상자를 닫을 수 있다는 것이다.사용자가 텍스트 상자에 정보를 입력하려고 시도조차 하지 않았기 때문에 유효성 검사 규칙은 실행되지 않습니다.
유효성 검사를 강제하여 일부 유효성 검사 규칙이 위반되었는지 확인할 수 있습니까?
사용자가 대화상자를 닫으려 할 때, 그리고 검증 규칙을 어기면 금지할 수 있습니다.
감사해요.
3.5SP1/3.0에서는SP2에서는 ValidationRule 기반에 ValidationsOnTargetUpdated=라는 새 속성도 추가했습니다."True". 이것은 타겟컨트롤이 갱신되었을 때뿐만 아니라 소스오브젝트가 바인드 되는 즉시 검증을 호출합니다.이것이 당신이 원하는 것은 아닐 수도 있지만, 당신이 수정해야 할 모든 것을 초기에 보는 것도 나쁘지 않다.
다음과 같이 동작합니다.
<TextBox.Text>
<Binding Path="Amount" StringFormat="C">
<Binding.ValidationRules>
<validation:RequiredValidationRule
ErrorMessage="The pledge amount is required."
ValidatesOnTargetUpdated="True" />
<validation:IsNumericValidationRule
ErrorMessage="The pledge amount must be numeric."
ValidationStep="ConvertedProposedValue"
ValidatesOnTargetUpdated="True" />
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
저희 어플리케이션에도 이 문제가 있습니다.검증은 바인딩이 갱신될 때만 실행되므로 수동으로 갱신해야 합니다.Window's Loaded 이벤트에서 다음을 수행합니다.
public void Window_Loaded(object sender, RoutedEventArgs e)
{
// we manually fire the bindings so we get the validation initially
txtName.GetBindingExpression(TextBox.TextProperty).UpdateSource();
txtCode.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}
그러면 오류 템플릿(빨간색 윤곽선)이 나타나고 검증이 설정됩니다.HasError 속성: OK 버튼을 트리거하여 비활성화합니다.
<Button x:Name="btnOK" Content="OK" IsDefault="True" Click="btnOK_Click">
<Button.Style>
<Style TargetType="{x:Type Button}">
<Setter Property="IsEnabled" Value="false" />
<Style.Triggers>
<!-- Require the controls to be valid in order to press OK -->
<MultiDataTrigger>
<MultiDataTrigger.Conditions>
<Condition Binding="{Binding ElementName=txtName, Path=(Validation.HasError)}" Value="false" />
<Condition Binding="{Binding ElementName=txtCode, Path=(Validation.HasError)}" Value="false" />
</MultiDataTrigger.Conditions>
<Setter Property="IsEnabled" Value="true" />
</MultiDataTrigger>
</Style.Triggers>
</Style>
</Button.Style>
</Button>
다음은 "UpdateSource()" 또는 "UpdateTarget()"을 호출하지 않아도 되는 대체 방법입니다.
var binding = thingToValidate.GetBinding(propertyToValidate);
foreach (var rule in binding.ValidationRules)
{
var value = thingToValidate.GetValue(propertyToValidate);
var result = rule.Validate(value, CultureInfo.CurrentCulture);
if (result.IsValid)
continue;
var expr = BindingOperations.GetBindingExpression(thingToValidate, propertyToValidate);
if (expr == null)
continue;
var validationError = new ValidationError(rule, expr);
validationError.ErrorContent = result.ErrorContent;
Validation.MarkInvalid(expr, validationError);
}
혹시나 이 오래된 질문을 발견하고 UI 가이드라인에 대한 Monstieur의 코멘트에 대한 답변을 찾고 있는 사람을 위해 다음과 같이 했습니다.
Xaml
<TextBox.Text>
<Binding Path="TextValue" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged">
<Binding.ValidationRules>
<local:RequiredFieldValidationRule>
<local:RequiredFieldValidationRule.IsRequiredField>
<local:BoolValue Value="{Binding Data.Required, Source={StaticResource proxy}}" />
</local:RequiredFieldValidationRule.IsRequiredField>
<local:RequiredFieldValidationRule.ValidationFailed>
<local:BoolValue Value="{Binding Data.HasValidationError, Mode=TwoWay, Source={StaticResource proxy}}" />
</local:RequiredFieldValidationRule.ValidationFailed>
</local:RequiredFieldValidationRule>
</Binding.ValidationRules>
</Binding>
</TextBox.Text>
RequiredFieldValidationRule:
public class RequiredFieldValidationRule : ValidationRule
{
private BoolValue _isRequiredField;
public BoolValue IsRequiredField
{
get { return _isRequiredField; }
set { _isRequiredField = value; }
}
private BoolValue _validationFailed;
public BoolValue ValidationFailed
{
get { return _validationFailed; }
set { _validationFailed = value; }
}
public override ValidationResult Validate(object value, CultureInfo cultureInfo)
{
ValidationFailed.Value = IsRequiredField.Value && (value == null || value.ToString().Length == 0);
return new ValidationResult(!ValidationFailed.Value, ValidationFailed.Value ? "This field is mandatory" : null);
}
}
Xaml이 바인드하는 클래스
private bool _hasValidationError;
public bool HasValidationError
{
get { return _hasValidationError; }
set { _hasValidationError = value; NotifyPropertyChanged(nameof(HasValidationError)); }
}
public void InitialisationMethod() // Or could be done in a constructor
{
_hasValidationError = Required; // Required is a property indicating whether the field is mandatory or not
}
그런 다음 개체 중 HasValidationError = true가 있는 경우 바인딩된 속성을 사용하여 저장 버튼을 숨깁니다.
이게 누군가에게 도움이 됐으면 좋겠다.
Robert Macnee가 제안한 위의 방법을 사용합니다.예를 들어 다음과 같습니다.
//force initial validation
foreach (FrameworkElement item in grid1.Children)
{
if (item is TextBox)
{
TextBox txt = item as TextBox;
txt.GetBindingExpression(TextBox.TextProperty).UpdateSource();
}
}
그러나 이 코드를 실행하기 전에 바인딩된 컨트롤이 표시 가능해야 합니다.
Inotify 사용데이터 개체에서 변경된 속성
public class MyObject : INotifyPropertyChanged
{
string _MyPropertyToBind = string.Empty;
public string MyPropertyToBind
{
get
{
return _MyPropertyToBind;
}
set
{
_MyPropertyToBind = value;
NotifyPropertyChanged("MyPropertyToBind");
}
}
public void NotifyPropertyChanged(string property)
{
if (this.PropertyChanged != null)
{
this.PropertyChanged(this, new PropertyChangedEventArgs(property));
}
}
#region INotifyPropertyChanged Members
public event PropertyChangedEventHandler PropertyChanged;
#endregion
}
컨트롤에 다음 코드를 추가할 수 있습니다.
<TextBox Text="{Binding MyPropertyToBind, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" >
텍스트 상자는 datacontext 객체의 속성 변경 이벤트(이 예에서는 MyObjet)에 등록하고 소스 데이터가 업데이트되었을 때 실행된다고 가정합니다.
자동으로 새로고침이 제어에 강제됩니다.
Update Target 메서드라고 부를 필요가 없습니다.
언급URL : https://stackoverflow.com/questions/483419/force-validation-on-bound-controls-in-wpf
'programing' 카테고리의 다른 글
Excel 문자열로 날짜 연결 (0) | 2023.04.16 |
---|---|
비대화형으로 'psql' 비밀번호를 지정하려면 어떻게 해야 합니까? (0) | 2023.04.16 |
마이크로소프트(MS.Office.Interop.Excel.ApplicationClass에 정의된 생성자가 없습니다. (0) | 2023.04.16 |
오늘 날짜에서 30일 전 날짜를 얻는 방법 (0) | 2023.04.16 |
cp 명령으로 파일을 대상으로 복사하는 데 필요한 폴더를 만드는 방법 (0) | 2023.04.11 |