效果图:
思路很简单,就是对现有控件进行扩充,在验证时加上一个动画效果,然后使用Popup弹出来
核心是一个用户控件(动画效果)HelpTip:
HelpTip.Xaml代码如下:
<UserControl x:Class="HahaMan.SLTools.Controls.HelpTip" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Width="20" Height="20"> <UserControl.Resources> <Storyboard x:Name="sbProliferation" RepeatBehavior="Forever"> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="haloFrame" Storyboard.TargetProperty="Width"> <LinearDoubleKeyFrame Value="35" KeyTime="0:0:0.7" /> <LinearDoubleKeyFrame Value="35" KeyTime="0:0:1.5" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="haloFrame" Storyboard.TargetProperty="Height"> <LinearDoubleKeyFrame Value="35" KeyTime="0:0:0.7" /> <LinearDoubleKeyFrame Value="35" KeyTime="0:0:1.5" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="haloFrame" Storyboard.TargetProperty="Opacity"> <LinearDoubleKeyFrame Value="0" KeyTime="0:0:0.7" /> <LinearDoubleKeyFrame Value="0" KeyTime="0:0:1.5" /> </DoubleAnimationUsingKeyFrames> <DoubleAnimationUsingKeyFrames Storyboard.TargetName="haloFrame" Storyboard.TargetProperty="StrokeThickness"> <LinearDoubleKeyFrame Value="1" KeyTime="0:0:0.7" /> <LinearDoubleKeyFrame Value="1" KeyTime="0:0:1.5" /> </DoubleAnimationUsingKeyFrames> </Storyboard> <Storyboard x:Name="sbLoaded"> <DoubleAnimation Storyboard.TargetName="buttonTransform" Storyboard.TargetProperty="ScaleX" From="2" To="1" Duration="0:0:0.5"> <DoubleAnimation.EasingFunction> <CubicEase EasingMode="EaseIn"/> </DoubleAnimation.EasingFunction> </DoubleAnimation> <DoubleAnimation Storyboard.TargetName="buttonTransform" Storyboard.TargetProperty="ScaleY" From="2" To="1" Duration="0:0:0.5"> <DoubleAnimation.EasingFunction> <CubicEase EasingMode="EaseIn"/> </DoubleAnimation.EasingFunction> </DoubleAnimation> <DoubleAnimation Storyboard.TargetName="LayoutRoot" Storyboard.TargetProperty="Opacity" To="1" Duration="0:0:0.5"> <DoubleAnimation.EasingFunction> <CubicEase EasingMode="EaseIn"/> </DoubleAnimation.EasingFunction> </DoubleAnimation> </Storyboard> <Storyboard x:Name="sbMsg"> <DoubleAnimation x:Name="aniOpacityMsgBackground" Storyboard.TargetName="canvasMessage" Storyboard.TargetProperty="Opacity" Duration="0:0:0.2" /> <DoubleAnimation x:Name="aniOpacityBlackLine" Storyboard.TargetName="blackLine" Storyboard.TargetProperty="Opacity" Duration="0:0:0.2" /> </Storyboard> </UserControl.Resources> <Canvas x:Name="LayoutRoot"> <Canvas.RenderTransform> <ScaleTransform ScaleX="1.0" ScaleY="1.0"/> </Canvas.RenderTransform> <TextBlock x:Name="txt1" Text="" Margin="20,-10"/> <TextBlock x:Name="txt2" Text="" Margin="20,5"/> <TextBlock x:Name="txt3" Text="" Margin="20,20"/> <Popup x:Name="popup"> <Canvas x:Name="canvasMessage" Opacity="0"> <Border x:Name="borderMessage" Background="#FFFFFF" BorderBrush="#515151" BorderThickness="1" CornerRadius="5"> <Grid x:Name="helpGrid" Margin="22 4 8 4"> <TextBlock x:Name="tbMessage" FontSize="12" LineStackingStrategy="BlockLineHeight" LineHeight="16" TextWrapping="Wrap" TextAlignment="Left" /> </Grid> <Border.RenderTransform> <TranslateTransform x:Name="translate" /> </Border.RenderTransform> </Border> <Grid Width="12" Height="12" Canvas.Left="5" Canvas.Top="5"> <Ellipse> <Ellipse.Fill> <RadialGradientBrush Center="0.5,0" GradientOrigin="0.5,0"> <GradientStop Color="#FFAA73" Offset="0" /> <GradientStop Color="#FF7012" Offset="0.6" /> <GradientStop Color="#F06405" Offset="1" /> </RadialGradientBrush> </Ellipse.Fill> <Ellipse.Effect> <DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5" Opacity="0.5" /> </Ellipse.Effect> </Ellipse> </Grid> </Canvas> </Popup> <Canvas x:Name="elementContainer"> <Grid Width="35" Height="35" Canvas.Left="-7" Canvas.Top="-7"> <Ellipse x:Name="haloFrame" Width="12" Height="12" Stroke="#F06405" StrokeThickness="3"> <Ellipse.Effect> <DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="2" Opacity="0.2" /> </Ellipse.Effect> </Ellipse> </Grid> <Grid x:Name="ellipse" Width="12" Height="12" Canvas.Left="5" Canvas.Top="5"> <Ellipse> <Ellipse.Fill> <RadialGradientBrush Center="0.5,0" GradientOrigin="0.5,0"> <GradientStop Color="#FFAA73" Offset="0" /> <GradientStop Color="#FF7012" Offset="0.6" /> <GradientStop Color="#F06405" Offset="1" /> </RadialGradientBrush> </Ellipse.Fill> <Ellipse.Effect> <DropShadowEffect Direction="0" ShadowDepth="0" BlurRadius="5" Opacity="0.5" /> </Ellipse.Effect> </Ellipse> <Grid x:Name="blackLine"> <Rectangle Width="6" Height="2" Fill="#000000" /> <Rectangle Width="2" Height="6" Fill="#000000" /> </Grid> <Grid.RenderTransform> <ScaleTransform x:Name="buttonTransform" CenterX="6" CenterY="6" /> </Grid.RenderTransform> </Grid> </Canvas> </Canvas></UserControl>
HelpTip.cs代码如下:
namespace HahaMan.SLTools.Controls{ partial class HelpTip : UserControl { private TimeSpan _loadDelay; [Category("HahaData")] public Thickness Text1Margin { get { return txt1.Margin; } set { txt1.Margin = value; } } [Category("HahaData")] public Thickness Text2Margin { get { return txt2.Margin; } set { txt2.Margin = value; } } [Category("HahaData")] public Thickness Text3Margin { get { return txt3.Margin; } set { txt3.Margin = value; } } [Category("HahaData")] public double Scale { get { return (LayoutRoot.RenderTransform as ScaleTransform).ScaleX; } set { var scale = (LayoutRoot.RenderTransform as ScaleTransform); scale.ScaleX = scale.ScaleY = value; } } [Category("HahaData")] public string Text1 { get{return txt1.Text;} set{txt1.Text = value;} } [Category("HahaData")] public string Text2 { get { return txt2.Text; } set { txt2.Text = value; } } [Category("HahaData")] public string Text3 { get { return txt3.Text; } set { txt3.Text = value; } } [Category("HahaData")] public double Text3FontSize { get { return txt3.FontSize; } set { txt3.FontSize = value; } } [Category("HahaData")] public double Text2FontSize { get { return txt2.FontSize; } set { txt2.FontSize = value; } } [Category("HahaData")] public double Text1FontSize { get { return txt1.FontSize; } set { txt1.FontSize = value; } } [Category("HahaData")] public Brush Text3Foreground { get { return txt3.Foreground; } set { txt3.Foreground = value; } } [Category("HahaData")] public Brush Text2Foreground { get { return txt2.Foreground; } set { txt2.Foreground = value; } } [Category("HahaData")] public Brush Text1Foreground { get { return txt1.Foreground; } set { txt1.Foreground = value; } } [Category("HahaData")] public string Message { get { return tbMessage.Text; } set { tbMessage.Text = value; } } public HelpTip() { this._loadDelay = TimeSpan.FromSeconds(0.0); this.InitializeComponent(); this.ellipse.MouseEnter += new MouseEventHandler(this.ellipse_MouseEnter); this.ellipse.MouseLeave += new MouseEventHandler(ellipse_MouseLeave); this.canvasMessage.MouseLeave += new MouseEventHandler(this.canvasMessage_MouseLeave); this.sbMsg.Completed += new EventHandler(this.sbMsg_Completed); this.sbLoaded.Completed += new EventHandler(this.sbLoaded_Completed); InitializeComponent(); sbLoaded.Begin(); } void ellipse_MouseLeave(object sender, MouseEventArgs e) { if (this.Message.Length == 0) { this.HideMessage(); } } private void ellipse_MouseEnter(object sender, MouseEventArgs e) { this.ShowMessage(); } private void sbMsg_Completed(object sender, EventArgs e) { if (this.aniOpacityMsgBackground.To <= 0.0) { this.tbMessage.Visibility = Visibility.Collapsed; this.canvasMessage.Visibility = Visibility.Collapsed; this.popup.IsOpen = false; } } private void canvasMessage_MouseLeave(object sender, MouseEventArgs e) { sbLoaded.Begin(); this.HideMessage(); } private void HideMessage() { sbProliferation.Resume(); base.SetValue(Canvas.ZIndexProperty, 0); this.aniOpacityMsgBackground.To = 0.0; this.aniOpacityBlackLine.To = 1.0; this.sbMsg.Begin(); } public void BeginHalo() { if (this.sbProliferation.GetCurrentState() == ClockState.Stopped) { this.haloFrame.Visibility = Visibility.Visible; this.sbProliferation.Begin(); } } private void sbLoaded_Completed(object sender, EventArgs e) { sbLoaded.Stop(); this.BeginHalo(); } private void ShowMessage() { sbLoaded.Begin(); sbProliferation.Pause(); this.aniOpacityMsgBackground.To = 0.9; this.aniOpacityBlackLine.To = 0.0; this.sbMsg.Begin(); if (Message.Length == 0) return; this.popup.IsOpen = true; base.SetValue(Canvas.ZIndexProperty, 1); this.tbMessage.Visibility = Visibility.Visible; this.canvasMessage.Visibility = Visibility.Visible; this.SetPostion(); } private Position _haloPosition; public Position Position { get { return _haloPosition; } set { _haloPosition = value; } } private void SetPostion() { this.borderMessage.UpdateLayout(); switch (this._haloPosition) { case Position.LeftTop: this.translate.X = 0.0; this.translate.Y = 0.0; this.helpGrid.Margin = new Thickness(22.0, 4.0, 8.0, 4.0); return; case Position.RightTop: this.translate.X = -this.borderMessage.ActualWidth + 22.0; this.helpGrid.Margin = new Thickness(8.0, 4.0, 22.0, 4.0); return; case Position.RightBottom: this.helpGrid.Margin = new Thickness(8.0, 4.0, 22.0, 4.0); return; case Position.LeftBottom: this.helpGrid.Margin = new Thickness(22.0, 4.0, 8.0, 4.0); return; } } } public enum Position { LeftTop, RightTop, RightBottom, LeftBottom }}
ValidTextBox.cs代码如下:
namespace HahaMan.SLTools.Controls{ public class ValidTextBox : TextBox { public static string EmptyString = "不为空!"; public static string NotIsInt = "请输入整数!"; public static string NotIsDouble = "请输入有效数字!"; public HelpTip help; public bool IsEmpty { get { if (this.Text.Length == 0) { this.Message = EmptyString; this.Focus(); return true; } this.Message = ""; return false; } } public int? ToInt { get { try { return int.Parse(this.Text); } catch { return null; } } } public double? ToDouble { get { try { return double.Parse(this.Text); } catch { return null; } } } public decimal? ToDecimal { get { try { return decimal.Parse(this.Text); } catch { return null; } } } public bool IsInt { get { try { if (IsEmpty) return false; int.Parse(this.Text); Message = ""; return true; } catch { Message = NotIsInt; return false; } } } public bool IsDouble { get { try { if (IsEmpty) return false; double.Parse(this.Text); Message = ""; return true; } catch { Message = NotIsDouble; return false; } } } public String Message { get { if (help == null) return ""; return help.Message; } set { if (help == null) { help = new HelpTip(); Panel fe = this.Parent as Panel; fe.Children.Add(help); help.Width = 20; help.Height = 20; help.HorizontalAlignment = this.HorizontalAlignment; help.VerticalAlignment = this.VerticalAlignment; help.Margin = new Thickness(this.Margin.Left + this.Width, this.Margin.Top, 0, 0); } help.Message = value; if (value.Length > 0) { help.Visibility = Visibility.Visible; } else { help.Visibility = Visibility.Collapsed; } } } }}
ValidComboBox.cs代码如下:
namespace HahaMan.SLTools.Controls{ public class ValidCombox:ComboBox { public HelpTip help; public String Message { get { if (help == null) return ""; return help.Message; } set { if (help == null) { help = new HelpTip(); Panel fe = this.Parent as Panel; fe.Children.Add(help); help.Width = 20; help.Height = 20; help.HorizontalAlignment = this.HorizontalAlignment; help.VerticalAlignment = this.VerticalAlignment; help.Margin = new Thickness(this.Margin.Left + this.Width, this.Margin.Top, 0, 0); } help.Message = value; if (value.Length > 0) { help.Visibility = Visibility.Visible; } else { help.Visibility = Visibility.Collapsed; } } } }}
测试按钮代码如下:
private void ibAdd_Click(object sender, RoutedEventArgs e) { if (txtName.IsEmpty) return; if (cbxSex.SelectedIndex == -1) { cbxSex.Message = "请选择..."; return; } else { cbxSex.Message = ""; } if (txtAge.IsEmpty || txtAge.IsInt == false) return; if (txtMoney.IsEmpty || txtMoney.IsDouble == false) return; }
代码路径:http://download.csdn.net/detail/lijun7788/4987454