效果图:
思路很简单,就是对现有控件进行扩充,在验证时加上一个动画效果,然后使用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