[英]How to force validation to show on UserControl
我希望帶有工具提示的股票/標准紅色邊框驗證能在我的UserControl周圍顯示。 見下面的代碼。 我有主頁面和UserControl。
UserControl有文本框和按鈕。 UserControls綁定到Id屬性並在TextBox中顯示此Id。
主頁包含UserControl和TextBox。 它們綁定到FirstValue和SecondValue。 這兩個屬性都會引發錯 當我在文本框中輸入/更改內容時 - 我看到邊框和摘要。 當我在UserControl中更改文本時-我看到摘要錯誤但沒有邊框,並且當我單擊錯誤時-它聚焦按鈕,不會轉到TextBox。 我該如何解決這個問題? 我希望整個UserControl位於紅色邊框內。
MainPage XAML:
<UserControl x:Class="SilverlightApplication1.MainPage"
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"
mc:Ignorable="d"
d:DesignHeight="275" d:DesignWidth="402" xmlns:my="clr-namespace:SilverlightApplication1" xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk">
<Grid x:Name="LayoutRoot" Background="White" Width="300" HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition Height="40" />
<RowDefinition Height="30" />
<RowDefinition Height="30" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<TextBox Grid.Row="2" Margin="3" Text="{Binding SecondValue, Mode=TwoWay, NotifyOnValidationError=True}"/>
<my:TestUserControl Margin="3" Id="{Binding FirstValue, Mode=TwoWay, NotifyOnValidationError=True}"/>
<sdk:ValidationSummary Grid.Row="4" Name="validationSummary1" />
</Grid>
</UserControl>
MainPage CS
using System.Windows.Controls;
namespace SilverlightApplication1
{
using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
public partial class MainPage : UserControl, INotifyDataErrorInfo, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public event EventHandler<DataErrorsChangedEventArgs> ErrorsChanged;
readonly Dictionary<string, List<string>> _currentErrors;
private string _firstValue;
private string _secondValue;
public MainPage()
{
InitializeComponent();
_currentErrors = new Dictionary<string, List<string>>();
_firstValue = "test1";
_secondValue = "test2";
LayoutRoot.DataContext = this;
}
public string FirstValue
{
get { return _firstValue; }
set
{
_firstValue = value;
CheckIfValueIsValid("FirstValue", value);
this.OnPropertyChanged("FirstValue");
}
}
public string SecondValue
{
get { return _secondValue; }
set
{
_secondValue = value;
CheckIfValueIsValid("SecondValue", value);
this.OnPropertyChanged("SecondValue");
}
}
public void CheckIfValueIsValid(string propertyName, string value)
{
ClearErrorFromProperty(propertyName);
AddErrorForProperty(propertyName, "Bad value");
}
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
public IEnumerable GetErrors(string propertyName)
{
if (string.IsNullOrEmpty(propertyName))
{
return (_currentErrors.Values);
}
MakeOrCreatePropertyErrorList(propertyName);
return _currentErrors[propertyName];
}
public bool HasErrors
{
get
{
return (_currentErrors.Where(c => c.Value.Count > 0).Count() > 0);
}
}
void FireErrorsChanged(string property)
{
if (ErrorsChanged != null)
{
ErrorsChanged(this, new DataErrorsChangedEventArgs(property));
}
}
public void ClearErrorFromProperty(string property)
{
MakeOrCreatePropertyErrorList(property);
_currentErrors[property].Clear();
FireErrorsChanged(property);
}
public void AddErrorForProperty(string property, string error)
{
MakeOrCreatePropertyErrorList(property);
_currentErrors[property].Add(error);
FireErrorsChanged(property);
}
void MakeOrCreatePropertyErrorList(string propertyName)
{
if (!_currentErrors.ContainsKey(propertyName))
{
_currentErrors[propertyName] = new List<string>();
}
}
}
}
UserControl XAML:
<UserControl x:Class="SilverlightApplication1.TestUserControl"
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"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="400">
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<Button Content="..." Grid.Column="1" Padding="10,0" />
<TextBox Text="{Binding Id, Mode=TwoWay}" />
</Grid>
</UserControl>
UserControl CS:
using System.Windows.Controls;
namespace SilverlightApplication1
{
using System.ComponentModel;
using System.Windows;
public partial class TestUserControl : UserControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public TestUserControl()
{
InitializeComponent();
LayoutRoot.DataContext = this;
}
public string Id
{
get { return (string)base.GetValue(IdProperty); }
set
{
base.SetValue(IdProperty, value);
this.OnPropertyChanged("Id");
}
}
public static DependencyProperty IdProperty =
DependencyProperty.Register(
"Id",
typeof(string),
typeof(TestUserControl),
new PropertyMetadata(OnIdChanged));
private static void OnIdChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
if (DesignerProperties.IsInDesignTool) return;
var lookup = d as TestUserControl;
lookup.OnPropertyChanged("Id");
}
protected void OnPropertyChanged(string propertyName)
{
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}
}
}
}
要使您的示例正常工作,您應該從TestUserControl.xaml.cs
文件中刪除所有代碼並修復綁定。 像這樣:
<Button Content="..." Grid.Column="1" Padding="10,0" />
<TextBox Text="{Binding FirstValue, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnNotifyDataErrors=True}" />
並且空代碼背后:
public partial class TestUserControl : UserControl
{
public TestUserControl()
{
InitializeComponent();
}
}
接下來,您的另一個問題
在所有3個框周圍顯示紅色邊框(一個矩形)
可以通過綁定到HasError
屬性來實現。 根據你的代碼,它看起來如此:
<Grid x:Name="LayoutRoot" Background="White">
<!-- ... -->
<Border BorderBrush="Red" BorderThickness="1"
Grid.ColumnSpan="2" IsHitTestVisible="False"
Visibility="{Binding HasErrors, Converter={StaticResource BooleanToVisibilityConverter}}" />
我添加了紅色的Border
元素,當HasError
屬性設置為true時,該元素變為可見。 但是你應該在代碼中的某個地方調用OnPropertyChanged("HasError")
。
另一種方法:創建自定義控件而不是UserControl。 我已經過多地描述了如何在自定義控件中實現驗證,作為對此驗證問題的解答。
我可以給出一個更具體的答案,但是您應該通過將視圖模型與視圖分離來修復帖子中的代碼,因為現在很難基於當前代碼來實現某些東西。 使用INotifyDataErrorInfo檢查我的帖子有關驗證的實現: WPF和Silverlight驗證 。
或者,您可以直接下載我的驗證類。
之后代碼將變得更加簡單,我將能夠幫助您解決更復雜的問題。
更改
<TextBox Text="{Binding Id, Mode=TwoWay}" />
至
<TextBox Text="{Binding Id, Mode=TwoWay, NotifyOnValidationError=True, ValidatesOnDataErrors=True}" />
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.