WPF 有趣的动画效果
WPF 有趣的动画效果
这是非常令人沮丧的。如此简单的东西(而且是大多开发者会考虑寻找的东西)在WPF中却不被觉得是绘制形状的要求。
我跑题了。如今我们什么也做不了。
你能够使用Blend。可是由于我们大多数要输入代码。Blend可能有点过度了。
<Window x:Class="WpfAnimationTest.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="WPF Animation Testing" Height="600" Width="800" WindowStartupLocation="CenterScreen"> <Canvas x:Name="Root" Background="Black"> </Canvas> </Window>你会看到。除了将背景变为黑色,我们改变了默认的grid为canvas。而且设置了窗口大小和标题。
改变的也不多。不像大多说WPF/XAML项目,这里我们画的大部分用代码实现。
首先是一点儿理论
比如,假设你想要在中间使用从红到蓝颜色渐变,然后变绿,你可能在0%处创建红色点。在50%创建蓝色,100%处创建绿色。
WPF图画引擎然后在全部颜色间填充。这样你就得到从一个颜色到下一个的平滑过渡。
public MainWindow() { InitializeComponent(); Rectangle myRect = new Rectangle { Width = 300, Height = 100, Stroke = Brushes.White, StrokeThickness = 1 }; Root.Children.Add(myRect); Canvas.SetLeft(myRect, 100); Canvas.SetTop(myRect, 100); }当你按下F5,你应该能看到黑色背景上白色矩形,距离每一个角都是100像素。大小300像素*100像素。须要Canvas SetLeft和SetTop调用,是由于微软决定同意绘制闭环形状的不论什么人来决定形状绘制的位置时没实用处的。
public MainWindow() { InitializeComponent(); Rectangle myRect = new Rectangle { Width = 300, Height = 100, Stroke = Brushes.White, StrokeThickness = 1, Fill=Brushes.Red }; Root.Children.Add(myRect); Canvas.SetLeft(myRect, 100); Canvas.SetTop(myRect, 100); }你也能够设置矩形全局的实心填充颜色。
然而。实心颜色有点无趣。
我们将改动成更加有趣的东西。
输入例如以下代码:
namespace WpfAnimationTest { public class BarDescriptor { public int RectangleX { get; set; } public int RectangleY { get; set; } public int RectangleWidth { get; set; } public int RectangleHeight { get; set; } public int AnimationTimeInSeconds { get; set; } // 0.0 to 1.0 public float BarBaseRedLevel { get; set; } public float BarBaseGreenLevel { get; set; } public float BarBaseBlueLevel { get; set; } public float GradientStartX { get; set; } public float GradientStartY { get; set; } public float GradientEndX { get; set; } public float GradientEndY { get; set; } } }确保依照你的须要改动了命名空间。
using System; using System.Linq; using System.Text.RegularExpressions; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace WpfAnimationTest { public partial class MainWindow { private Rectangle _testRect; public MainWindow() { InitializeComponent(); Loaded += MainWindowLoaded; } private void MainWindowLoaded(object sender, RoutedEventArgs e) { BarDescriptor barOne = new BarDescriptor { RectangleX = 100, RectangleY = 100, RectangleWidth = 200, RectangleHeight = 200, AnimationTimeInSeconds = 0, BarBaseRedLevel = 0, BarBaseGreenLevel = 0, BarBaseBlueLevel = 0, GradientStartX = 0, GradientStartY = 0, GradientEndX = 0, GradientEndY = 0 }; CreateRectangleAnimatedRectangle(barOne); } private void CreateRectangleAnimatedRectangle(BarDescriptor inputParameters) { _testRect = new Rectangle { Width = inputParameters.RectangleWidth, Height = inputParameters.RectangleHeight, Stroke = Brushes.White, StrokeThickness = 1, }; Root.Children.Add(_testRect); Canvas.SetLeft(_testRect, inputParameters.RectangleX); Canvas.SetTop(_testRect, inputParameters.RectangleY); } } }再一次。确保输入正确的命名空间。正如之前的样例,执行时你应该又看到白色矩形。可是如今你也应该可以轻松加入新矩形。通过创建新的“BarDescriptor”对象,并设置对应參数。
BarDescriptor barOne = new BarDescriptor { RectangleX = 0, RectangleY = 0, RectangleWidth = 800, RectangleHeight = 600, AnimationTimeInSeconds = 0, BarBaseRedLevel = 0, BarBaseGreenLevel = 0, BarBaseBlueLevel = 0, GradientStartX = 0, GradientStartY = 0, GradientEndX = 0, GradientEndY = 0 };这样会创建和主窗体相同大小的矩形。
透明度的设置同意你控制多少背景、多少颜色显示出来。
GradientStopCollection gradientStops = new GradientStopCollection { new GradientStop(Color.FromScRgb(0.0f, 1, 1, 1), 0.0), new GradientStop(Color.FromScRgb(0.0f, 1, 1, 1), 0.01), new GradientStop(Color.FromScRgb(0.5f, 1, 1, 1), 0.02), new GradientStop(Color.FromScRgb(1.0f, 1, 1, 1), 0.03), new GradientStop(Color.FromScRgb(0.5f, 1, 1, 1), 0.04), new GradientStop(Color.FromScRgb(0.0f, 1, 1, 1), 0.05), new GradientStop(Color.FromScRgb(0.0f, 1, 1, 1), 1.0), };这一系列的渐变点创建了一系列七色点全白(R/G/B值都为1),颜色点被设置沿着渐变填充长度 位置为0, 0.01, 0.02, 0.03, 0.04, 0.05,和1。而且有透明度0, 0, 0.5, 1, 0.5, 0 和0。这系列填充意味着我们从第一个点到第二个点透明,然后突然从全然透明升级为实心白色,紧接着突然降回透明;最后,从点6和点7(矩形的剩余部分)是100%透明。
LinearGradientBrush gradientBrush = new LinearGradientBrush(gradientStops, new Point(0, 0.5), new Point(1, 0.5));这将使用点集创建实际的渐变。它将横跨Y坐标系,沿着X轴从0到100%(1)水平执行。
一旦你添加了渐变。改动了矩形创建參数来设置渐变,当你这样做了。也会使得边界消失:
_testRect = new Rectangle { Width = inputParameters.RectangleWidth, Height = inputParameters.RectangleHeight, Stroke = Brushes.Transparent, StrokeThickness = 0, Fill = gradientBrush };这些都做好后,执行你的应用程序,你会得到:
你应该可以直接看到不同透明度的影响。以及它导致填充圆柱形3D条外观的效果。为了实现动画。我们须要移动5个渐变点,组成渐变部分看起来像3D条。在上面的渐变点集中。这些值是5个值。位于两个外部值之间,位置从0.01到0.05.
- 点1从0.01到0.95并返回;
- 点2从0.02到0.96并返回;
- 点3从0.03到0.97并返回。
- 点4从0.04到0.98并返回;
- 点5从0.05到0.99并返回。
DoubleAnimation firstStopAnim =new DoubleAnimation(0.01, 0.95,new Duration(new TimeSpan(0, 0, 0, 5))); DoubleAnimation secondStopAnim = new DoubleAnimation(0.02, 0.96,new Duration(new TimeSpan(0, 0, 0, 5))); DoubleAnimation thirdStopAnim = new DoubleAnimation(0.03, 0.97,new Duration(new TimeSpan(0, 0, 0, 5))); DoubleAnimation fourthStopAnim = new DoubleAnimation(0.04, 0.98,new Duration(new TimeSpan(0, 0, 0, 5))); DoubleAnimation fifthStopAnim = new DoubleAnimation(0.05, 0.99,new Duration(new TimeSpan(0, 0, 0, 5))); firstStopAnim.AutoReverse = true; secondStopAnim.AutoReverse = true; thirdStopAnim.AutoReverse = true; fourthStopAnim.AutoReverse = true; fifthStopAnim.AutoReverse = true; firstStopAnim.BeginTime = new TimeSpan(0); secondStopAnim.BeginTime = new TimeSpan(0); thirdStopAnim.BeginTime = new TimeSpan(0); fourthStopAnim.BeginTime = new TimeSpan(0); fifthStopAnim.BeginTime = new TimeSpan(0); firstStopAnim.EasingFunction = new CubicEase(); secondStopAnim.EasingFunction = new CubicEase(); thirdStopAnim.EasingFunction = new CubicEase(); fourthStopAnim.EasingFunction = new CubicEase(); fifthStopAnim.EasingFunction = new CubicEase();这里我们加入5个点,然后设置默认属性,以及范围。默认属性是自己主动返回相反方向,从0s開始,使用CubicEase动画转变。
一旦我们创建动画对象。我们然后须要给内部5个渐变点以独特的名称,这样我们能够附加故事板对象控制他们的动画。
String slotOneName = RandomName(); String slotTwoName = RandomName(); String slotThreeName = RandomName(); String slotFourName = RandomName(); String slotFiveName = RandomName(); RegisterName(slotOneName, gradientStops[1]); RegisterName(slotTwoName, gradientStops[2]); RegisterName(slotThreeName, gradientStops[3]); RegisterName(slotFourName, gradientStops[4]); RegisterName(slotFiveName, gradientStops[5]);函数“RandomName”是用户加入的函数,放在绘制矩形方法之后。
你须要给每一个名称一个随机名,这样你能够重用矩形绘制方法。假设你尝试重用已经被分配给之前颜色点的名称,矩形函数将终止,可是你不会得到阻止应用程序的异常。而是得到黑色窗体,没有不论什么动画。因此确保你的点名称唯一是非常重要的,可是没有混乱到你给出不可用的属性名。
我在这里使用的函数使用了随机和一个GUID结合的方式,没有危急的字符。
为了在你的代码中定义它。在MainWindow类中,矩形函数之后加入例如以下代码:
private string RandomName() { const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const int nameLen = 8; var random = new Random(); string temp = Guid.NewGuid().ToString(). Replace("-", String.Empty); temp = Regex.Replace(temp, @"[\d-]", string.Empty).ToUpper(); return new string(Enumerable.Repeat(chars, nameLen).Select (s => s[random.Next(s.Length)]).ToArray()) + temp; }随机名称设置好以后,我们然后開始在矩形函数中设置渐变动画。
下一件事是映射我们刚创建的随机属性名,附加渐变点到故事板。
我们使用WPF故事板类的静态属性来匹配,然后创建故事板局部对象,加入每一个动画到子集合。
Storyboard.SetTargetName(firstStopAnim, slotOneName); Storyboard.SetTargetProperty(firstStopAnim,new PropertyPath(GradientStop.OffsetProperty)); Storyboard.SetTargetName(secondStopAnim, slotTwoName); Storyboard.SetTargetProperty(secondStopAnim,new PropertyPath(GradientStop.OffsetProperty)); Storyboard.SetTargetName(thirdStopAnim, slotThreeName); Storyboard.SetTargetProperty(thirdStopAnim,new PropertyPath(GradientStop.OffsetProperty)); Storyboard.SetTargetName(fourthStopAnim, slotFourName); Storyboard.SetTargetProperty(fourthStopAnim,new PropertyPath(GradientStop.OffsetProperty)); Storyboard.SetTargetName(fifthStopAnim, slotFiveName); Storyboard.SetTargetProperty(fifthStopAnim,new PropertyPath(GradientStop.OffsetProperty)); Storyboard gradientAnimation = new Storyboard { RepeatBehavior = RepeatBehavior.Forever }; gradientAnimation.Children.Add(firstStopAnim); gradientAnimation.Children.Add(secondStopAnim); gradientAnimation.Children.Add(thirdStopAnim); gradientAnimation.Children.Add(fourthStopAnim); gradientAnimation.Children.Add(fifthStopAnim);然后紧接着加入例如以下梦幻般的代码,放置在矩形方法末尾,在设置矩形left和top之后:
gradientAnimation.Begin(this);假设一切正常进行。按下F5你会看到3D条左右来回移动。
AnimationTimeInSeconds是你想让故事板从矩形左側到右側执行的时间。这不包括返回时间。仅仅是动画一圈的时间。 BarBaseRedLevel, BarBaseGreenLevel,和BarBaseBlueLevel被用来设置条的基色。设置这些能够用来改变条的总体颜色。
BarDescriptor barOne = new BarDescriptor { RectangleX = 0, RectangleY = 0, RectangleWidth = 800, RectangleHeight = 600, AnimationTimeInSeconds = 5, BarBaseRedLevel = 0, BarBaseGreenLevel = 0.5f, BarBaseBlueLevel = 0, GradientStartX = 0, GradientStartY = 0.5f, GradientEndX = 1, GradientEndY = 0.5f };然后改动“CreateRectangle”方法使得參数被用在须要的地方。
改动渐变点集的创建,让它看起来例如以下:
GradientStopCollection gradientStops = new GradientStopCollection { new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.0), new GradientStop(Color.FromScRgb(0.0f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.01), new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.02), new GradientStop(Color.FromScRgb(1.0f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.03), new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.04), new GradientStop(Color.FromScRgb(0.0f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.05), new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 1.0), };然后。改动你创建线性渐变笔刷的行,看起来例如以下:
LinearGradientBrush gradientBrush = new LinearGradientBrush(gradientStops,new Point(inputParameters.GradientStartX, inputParameters.GradientStartY),new Point(inputParameters.GradientEndX,inputParameters.GradientEndY));假设一切顺利,你应该有一个绿色条左右移动,和之前相比有轻微渐变:
假设你看到上图,恭喜你。
如今须要做的就是把剩余的条加入上去,创建很多其它“BarDescriptor”对象,将它们传送到矩形创建方法例如以下:
BarDescriptor barOne = new BarDescriptor { RectangleX = 0, RectangleY = 0, RectangleWidth = 800, RectangleHeight = 600, AnimationTimeInSeconds = 5, BarBaseRedLevel = 0, BarBaseGreenLevel = 0.5f, BarBaseBlueLevel = 0, GradientStartX = 0, GradientStartY = 0.5f, GradientEndX = 1, GradientEndY = 0.5f }; BarDescriptor barTwo = new BarDescriptor { RectangleX = 0, RectangleY = 0, RectangleWidth = 800, RectangleHeight = 600, AnimationTimeInSeconds = 4, BarBaseRedLevel = 0, BarBaseGreenLevel = 0.5f, BarBaseBlueLevel = 0, GradientStartX = 1, GradientStartY = 0, GradientEndX = 0, GradientEndY = 1 }; BarDescriptor barThree = new BarDescriptor { RectangleX = 0, RectangleY = 0, RectangleWidth = 800, RectangleHeight = 600, AnimationTimeInSeconds = 3, BarBaseRedLevel = 0, BarBaseGreenLevel = 0.5f, BarBaseBlueLevel = 0, GradientStartX = 0, GradientStartY = 0, GradientEndX = 1, GradientEndY = 1 }; BarDescriptor barFour = new BarDescriptor { RectangleX = 0, RectangleY = 0, RectangleWidth = 800, RectangleHeight = 600, AnimationTimeInSeconds = 6, BarBaseRedLevel = 0, BarBaseGreenLevel = 0.5f, BarBaseBlueLevel = 0, GradientStartX = 0.5f, GradientStartY = 0, GradientEndX = 0.5f, GradientEndY = 1 }; CreateRectangleAnimatedRectangle(barOne); CreateRectangleAnimatedRectangle(barTwo); CreateRectangleAnimatedRectangle(barThree); CreateRectangleAnimatedRectangle(barFour);本文中开头用的图片就是四个条相互覆盖的产品,同意透明度相互结合。更改时间和更改速度有同样效果。所以不同条移动速度不一样。
仅仅是要记住,为了可以正常执行,你必须在中心有5个渐变,集合中有5个点。
using System; using System.Linq; using System.Text.RegularExpressions; using System.Windows; using System.Windows.Controls; using System.Windows.Media; using System.Windows.Media.Animation; using System.Windows.Shapes; namespace WpfAnimationTest { public partial class MainWindow { private Rectangle _testRect; public MainWindow() { InitializeComponent(); Loaded += MainWindowLoaded; } private void MainWindowLoaded(object sender, RoutedEventArgs e) { BarDescriptor barOne = new BarDescriptor { RectangleX = 0, RectangleY = 0, RectangleWidth = 800, RectangleHeight = 600, AnimationTimeInSeconds = 5, BarBaseRedLevel = 0, BarBaseGreenLevel = 0.5f, BarBaseBlueLevel = 0, GradientStartX = 0, GradientStartY = 0.5f, GradientEndX = 1, GradientEndY = 0.5f }; BarDescriptor barTwo = new BarDescriptor { RectangleX = 0, RectangleY = 0, RectangleWidth = 800, RectangleHeight = 600, AnimationTimeInSeconds = 4, BarBaseRedLevel = 0, BarBaseGreenLevel = 0.5f, BarBaseBlueLevel = 0, GradientStartX = 1, GradientStartY = 0, GradientEndX = 0, GradientEndY = 1 }; BarDescriptor barThree = new BarDescriptor { RectangleX = 0, RectangleY = 0, RectangleWidth = 800, RectangleHeight = 600, AnimationTimeInSeconds = 3, BarBaseRedLevel = 0, BarBaseGreenLevel = 0.5f, BarBaseBlueLevel = 0, GradientStartX = 0, GradientStartY = 0, GradientEndX = 1, GradientEndY = 1 }; BarDescriptor barFour = new BarDescriptor { RectangleX = 0, RectangleY = 0, RectangleWidth = 800, RectangleHeight = 600, AnimationTimeInSeconds = 6, BarBaseRedLevel = 0, BarBaseGreenLevel = 0.5f, BarBaseBlueLevel = 0, GradientStartX = 0.5f, GradientStartY = 0, GradientEndX = 0.5f, GradientEndY = 1 }; CreateRectangleAnimatedRectangle(barOne); CreateRectangleAnimatedRectangle(barTwo); CreateRectangleAnimatedRectangle(barThree); CreateRectangleAnimatedRectangle(barFour); } private void CreateRectangleAnimatedRectangle(BarDescriptor inputParameters) { DoubleAnimation firstStopAnim =new DoubleAnimation(0.01, 0.95,new Duration(new TimeSpan(0, 0, 0, 5))); DoubleAnimation secondStopAnim = new DoubleAnimation(0.02, 0.96,new Duration(new TimeSpan(0, 0, 0, 5))); DoubleAnimation thirdStopAnim = new DoubleAnimation(0.03, 0.97,new Duration(new TimeSpan(0, 0, 0, 5))); DoubleAnimation fourthStopAnim = new DoubleAnimation(0.04, 0.98,new Duration(new TimeSpan(0, 0, 0, 5))); DoubleAnimation fifthStopAnim = new DoubleAnimation(0.05, 0.99,new Duration(new TimeSpan(0, 0, 0, 5))); firstStopAnim.AutoReverse = true; secondStopAnim.AutoReverse = true; thirdStopAnim.AutoReverse = true; fourthStopAnim.AutoReverse = true; fifthStopAnim.AutoReverse = true; firstStopAnim.BeginTime = new TimeSpan(0); secondStopAnim.BeginTime = new TimeSpan(0); thirdStopAnim.BeginTime = new TimeSpan(0); fourthStopAnim.BeginTime = new TimeSpan(0); fifthStopAnim.BeginTime = new TimeSpan(0); firstStopAnim.EasingFunction = new CubicEase(); secondStopAnim.EasingFunction = new CubicEase(); thirdStopAnim.EasingFunction = new CubicEase(); fourthStopAnim.EasingFunction = new CubicEase(); fifthStopAnim.EasingFunction = new CubicEase(); GradientStopCollection gradientStops = new GradientStopCollection { new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.0), new GradientStop(Color.FromScRgb(0.0f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.01), new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.02), new GradientStop(Color.FromScRgb(1.0f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.03), new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.04), new GradientStop(Color.FromScRgb(0.0f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 0.05), new GradientStop(Color.FromScRgb(0.5f,inputParameters.BarBaseRedLevel,inputParameters.BarBaseGreenLevel,inputParameters.BarBaseBlueLevel), 1.0), }; String slotOneName = RandomName(); String slotTwoName = RandomName(); String slotThreeName = RandomName(); String slotFourName = RandomName(); String slotFiveName = RandomName(); RegisterName(slotOneName, gradientStops[1]); RegisterName(slotTwoName, gradientStops[2]); RegisterName(slotThreeName, gradientStops[3]); RegisterName(slotFourName, gradientStops[4]); RegisterName(slotFiveName, gradientStops[5]); LinearGradientBrush gradientBrush = new LinearGradientBrush(gradientStops,new Point(inputParameters.GradientStartX, inputParameters.GradientStartY),new Point(inputParameters.GradientEndX,inputParameters.GradientEndY)); Storyboard.SetTargetName(firstStopAnim, slotOneName); Storyboard.SetTargetProperty(firstStopAnim,new PropertyPath(GradientStop.OffsetProperty)); Storyboard.SetTargetName(secondStopAnim, slotTwoName); Storyboard.SetTargetProperty(secondStopAnim,new PropertyPath(GradientStop.OffsetProperty)); Storyboard.SetTargetName(thirdStopAnim, slotThreeName); Storyboard.SetTargetProperty(thirdStopAnim,new PropertyPath(GradientStop.OffsetProperty)); Storyboard.SetTargetName(fourthStopAnim, slotFourName); Storyboard.SetTargetProperty(fourthStopAnim,new PropertyPath(GradientStop.OffsetProperty)); Storyboard.SetTargetName(fifthStopAnim, slotFiveName); Storyboard.SetTargetProperty(fifthStopAnim,new PropertyPath(GradientStop.OffsetProperty)); Storyboard gradientAnimation = new Storyboard { RepeatBehavior = RepeatBehavior.Forever }; gradientAnimation.Children.Add(firstStopAnim); gradientAnimation.Children.Add(secondStopAnim); gradientAnimation.Children.Add(thirdStopAnim); gradientAnimation.Children.Add(fourthStopAnim); gradientAnimation.Children.Add(fifthStopAnim); _testRect = new Rectangle { Width = inputParameters.RectangleWidth, Height = inputParameters.RectangleHeight, Stroke = Brushes.White, StrokeThickness = 1, Fill=gradientBrush }; Root.Children.Add(_testRect); Canvas.SetLeft(_testRect, inputParameters.RectangleX); Canvas.SetTop(_testRect, inputParameters.RectangleY); gradientAnimation.Begin(this); } private string RandomName() { const string chars = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"; const int nameLen = 8; var random = new Random(); string temp = Guid.NewGuid().ToString(). Replace("-", String.Empty); temp = Regex.Replace(temp, @"[\d-]", string.Empty).ToUpper(); return new string(Enumerable.Repeat(chars, nameLen).Select (s => s[random.Next(s.Length)]).ToArray()) + temp; } } }