UWP app .cs file inheritance static variable from xaml.cs - c#

I have created a PlayPage.xaml, PlayPage.xaml.cs and Game.cs file.
The PlayPage.xaml.cs has two variable, windowWidth and windowHeight.
I would like access two public static variable from Game.cs.
Game.cs:
namespace UwpApp
{
class Game
{
static Rectangle rectangle;
PlayPage pg = new PlayPage();
//Create a rectangle
public Rectangle draw()
{
rectangle = new Rectangle();
rectangle.Width = 70;
rectangle.Height = 70;
rectangle.Fill = new SolidColorBrush(Colors.Green);
Canvas.SetLeft(rectangle, randPos());
Canvas.SetTop(rectangle, randPos());
return rectangle;
}
//Create a random X and Y position
private Int32 randPos()
{
Random rnd = new Random();
Debug.WriteLine(pg.windowWidth);
return rnd.Next(0 , (int)pg.windowWidth);
}
}
}
PlayPage.xaml.cs:
namespace UwpApp
{
/// <summary>
/// An empty page that can be used on its own or navigated to within a Frame.
/// </summary>
public partial class PlayPage : Page
{
DispatcherTimer timer;
Rectangle rect;
bool isTapped;
public static double windowWidth, windowHeight;
Game game = new Game();
public PlayPage()
{
this.InitializeComponent();
startCounter.Visibility = Visibility.Collapsed;
isTapped = false;
}
private void Load_Variable(object sender, RoutedEventArgs e)
{
windowWidth = canvas.ActualWidth;
windowHeight = canvas.ActualHeight;
}
//Counter animation. (Number opacity, fall)
private void counterAnimation()
{
startCounter.Visibility = Visibility.Visible;
//Set Counter Horizontal Align
double left = (canvas.ActualWidth - startCounter.ActualWidth) / 2;
Canvas.SetLeft(startCounter, left);
Storyboard storyboard = new Storyboard();
DoubleAnimation opacityAnim = new DoubleAnimation();
DoubleAnimation fallAnim = new DoubleAnimation();
opacityAnim.From = 1;
opacityAnim.To = 0;
opacityAnim.Duration = new Duration(TimeSpan.FromSeconds(1));
opacityAnim.AutoReverse = false;
opacityAnim.RepeatBehavior = new RepeatBehavior(3);
Storyboard.SetTarget(opacityAnim, this.startCounter);
Storyboard.SetTargetProperty(opacityAnim, "(UIElement.Opacity)");
fallAnim.From = -115;
fallAnim.To = canvas.ActualHeight / 2;
fallAnim.Duration = new Duration(TimeSpan.FromSeconds(1));
fallAnim.AutoReverse = false;
fallAnim.RepeatBehavior = new RepeatBehavior(3);
Storyboard.SetTarget(fallAnim, this.startCounter);
Storyboard.SetTargetProperty(fallAnim, "(Canvas.Top)");
storyboard.Children.Add(opacityAnim);
storyboard.Children.Add(fallAnim);
storyboard.Begin();
}
//Countdown Timer
private void countDown()
{
timer = new DispatcherTimer();
timer.Tick += startCounter_CountDown;
timer.Interval = new TimeSpan(0, 0, 1);
timer.Start();
}
//Change Countdown value
private void startCounter_CountDown(object sender, object e)
{
int counterNum = int.Parse(startCounter.Text);
counterNum -= 1;
startCounter.Text = counterNum.ToString();
if (counterNum == 1)
{
timer.Stop();
StartedGame();
}
}
//Tap or Click to start the game
private void TapToStart(object sender, TappedRoutedEventArgs e)
{
if(!isTapped)
{
isTapped = true;
counterAnimation();
countDown();
this.TapToStartText.Visibility = Visibility.Collapsed;
}
}
//Create rectangles
private void StartedGame()
{
rect = game.draw();
canvas.Children.Add(game.draw());
Debug.WriteLine(windowWidth.ToString());
}
}
}
One more thing: I get an error this line: PlayPage pg = new PlayPage();
Error (pic)

The error in your picture is due to infinite recursion, as it says. The constructor for Game instantiates a new PlayPage. The constructor for PlayPage instantiates a new Game. Which instantiates a new PlayPage. Which instantiates a new Game. and on and on.
Static members are accessed by class name, not by instance. Like so:
PlayPage.windowWidth

Related

How to make Form Visible in C#

I am trying to design a piano for an assignment in C#. I have created a MusicKey class which stores music keys (as well as a BlackMusicKey class). I am populating the panel, 'panel1' with music keys like this:
this.panel1.Controls.Add(bmk);
In the music key constructor, I am setting a location and size for each music key, as well as ensuring that Visibility is set to true. However, when I run the form, it is completely blank.
Is there something that I am missing? I am quite sure that there is nothing wrong with the visibility of the music keys, so surely there is something that I am missing with regards to making the panel visible.
Any help will be appreciated, thanks!
Note: I have also tried using panel1.Show() which still did not work.
All relevant code can be found down below:
MusicKeyClass:
class MusKey : System.Windows.Forms.Button
{
private int musicNote; //determines the pitch mapped to number
public MusKey(int iNote, int x, int y) : base()
{
musicNote = iNote;
this.Location = new System.Drawing.Point(x, y);
this.Size = new System.Drawing.Size(20, 80);
this.Visible = true;
}
public int getMusicNote()
{
return musicNote;
}
}
Form1 Class:
public partial class Form1 : Form
{
int count = 0;
int xLoc = 50;
int yLoc = 30;
int[] whitePitch = { 1, 3, 5, 6, 8, 10, 12, 13, 15, 17, 18, 20, 22, 24 };
Panel panel1 = new Panel();
System.Windows.Forms.Timer timer1 = new System.Windows.Forms.Timer();
Button button1 = new Button();
private void Form1_Load(object sender, EventArgs e)
{
this.Paint += new PaintEventHandler(function);
MusKey mk;
BlackMusKey bmk;
for (int k = 0; k < 14; k++)
{
int pitch = whitePitch[k];
int ixPos = k * 20;
mk = new MusKey(pitch, ixPos, yLoc);
mk.MouseDown += new MouseEventHandler(this.button1_MouseDown);
mk.MouseUp += new MouseEventHandler(this.button1_MouseUp);
this.panel1.Controls.Add(mk);
}
int xOffs = 20;
int[] blackPitch = { 2, 4, 7, 9, 11, 14, 16, 19, 21, 23 };
int[] xPos = { 10, 30, 70, 110, 150, 170, 210, 230, 250 };
const int yPosBlack = 50;
for (int k = 0; k < 10; k++)
{
int pitch = blackPitch[k];
int ixPos = xPos[k];
bmk = new BlackMusKey(pitch, ixPos, yPosBlack);
bmk.MouseDown += new System.Windows.Forms.MouseEventHandler(this.button1_MouseDown); //create event MouseDown
bmk.MouseUp += new System.Windows.Forms.MouseEventHandler(this.button1_MouseUp); //create event MouseUp
this.panel1.Controls.Add(bmk);
this.panel1.Controls[this.panel1.Controls.Count - 1].BringToFront();
}
}
SoundPlayer sp = new SoundPlayer();
int count1;
private void button1_MouseDown(object sender, MouseEventArgs e)
{
foreach (MusKey mk in this.panel1.Controls)
{
if (sender == mk)
{ //true for the specific key pressed on the Music Keyboard
if (e.Button == MouseButtons.Left)
{
timer1.Enabled = true; //variable of the Timer component
count = 0; //incremented by the timer1_Tick event handler
timer1.Start();
sp.SoundLocation = (mk.getMusicNote() + ".wav"); //might need to convert ToString() ??
sp.Play();
}
}
}
}
private void timer1_Tick(object sender, EventArgs e)
{
count = count++;
}
private void button1_MouseUp(object sender, MouseEventArgs e)
{
foreach (MusKey mk in this.panel1.Controls)
{
if (sender == mk) //true for the specific key pressed on the Music Keyboard
{
if (e.Button == MouseButtons.Left)
{
timer1.Enabled = false;
sp.Stop();
string bNoteShape = null;
int duration = 0;
if (count >= 16)
{
bNoteShape = "SemiBreve";
duration = 16;
}
if (count >= 8 && count <= 15)
{
bNoteShape = "DotMinim";
duration = (8 + 15) / 2;
}
if (count >= 4 && count <= 7)
{
bNoteShape = "Crotchet";
duration = (4 + 7) / 2;
}
if (count >= 2 && count <= 3)
{
bNoteShape = "Quaver";
duration = (2 + 3) / 2;
}
if (count >= 1)
{
bNoteShape = "Semi-Quaver";
duration = 1;
}
MusicNote mn = new MusicNote(mk.getMusicNote(), duration, bNoteShape); //music note construction
// mn.Location = new Point(xLoc, yLoc);
//this.panel2.Controls.Add(this.mn); //adding MusicNote component to MusicStaff (panel2) collection
xLoc = xLoc + 15;
}
}
}
}
private void function(object sender, PaintEventArgs e)
{
panel1.Show();
panel1.Visible = true;
panel1.BackColor = Color.Blue;
panel1.Size = new Size(5, 5);
panel1.Location = new Point(3, 3);
this.Controls.Add(panel1);
this.Controls.Add(button1);
}
private void Form1_Load_1(object sender, EventArgs e)
{
}
}
Form 1 [designer] Class:
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.SuspendLayout();
//
// Form1
//
this.AutoScaleDimensions = new System.Drawing.SizeF(9F, 20F);
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Name = "Form1";
this.Text = "Form1";
this.Load += new System.EventHandler(this.Form1_Load_1);
this.ResumeLayout(false);
}
#endregion
}
Music Note Class
class MusicNote
{
public int notepitch;
public String noteshape;
public int noteduration;
enum accid { sharp, flat, sole };
bool dragging = false;
System.Timers.Timer timer1 = new System.Timers.Timer();
public MusicNote(int iNotepitch, int iDuration, String iBnoteShape)
{
notepitch = iNotepitch;
noteduration = iDuration;
noteshape = iBnoteShape;
}
bool timeron = false;
bool changenote = false;
public static int start = 0;
//public void click(object sender, MouseEventArgs e) { }
//public void RightPress(object sender, MouseEventArgs e) { }
}
}
Black Music Key Class
class BlackMusKey : MusKey
{
public BlackMusKey(int iNote, int x, int y) : base(iNote, x, y)
{
this.BackColor = Color.Black;
this.Size = new System.Drawing.Size(20, 60);
}
}
Program Class
static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
Application.EnableVisualStyles();
Application.SetCompatibleTextRenderingDefault(false);
Application.Run(new Form1());
}
}
According to Form1 class code, there is constructor missing. Please add proper constructor with InitializeComponent() method call. It can be added anywhere in class body.
Code snippet:
public partial class Form1 : Form
{
[...] //your objects declarations
public Form1()
{
InitializeComponent();
}
[...] //rest of your code
}

C# one timer for multiple shapes

For a school project I need to make a small game where multiple Ellipses move.
The last one that gets made with my method to make multiple at the same time moves with the timer I make.
How do you make one timer for all the Ellipses.
class EnemyTeam
{
private Ellipse enemy;
private Canvas canvas;
private double xChange = 50, yChange = 50;
public DispatcherTimer enemyTimer;
private char direction = '0';
private Thickness enemyThickness;
public EnemyTeam(Canvas canvas, double startPosition, SolidColorBrush playerBrush)
{
this.canvas = canvas;
DrawTeam(canvas, 40, playerBrush);
enemyTimer.Interval = TimeSpan.FromMilliseconds(100);
enemyTimer.Start();
}
private void DrawBall(SolidColorBrush brush, Canvas canvas,double x,double y)
{
enemy = new Ellipse();
enemy.Stroke = brush;
enemy.Fill = brush;
enemy.Height = 30;
enemy.Width = 30;
enemy.Margin = new Thickness(x,y, 0, 0);
enemyTimer = new DispatcherTimer();
enemyThickness = enemy.Margin;
canvas.Children.Add(enemy);
enemyTimer.Tick += enemyTimer_Tick;
}
void enemyTimer_Tick(object sender, EventArgs e)
{
if (enemyThickness.Left >= canvas.Width - 100)
{
GoDown();
direction = '1';
}
if (enemyThickness.Left <= 0 + 20)
{
GoDown();
direction = '0';
}
MoveTeam(enemy);
}
private void MoveTeam(Ellipse enemy)
{
enemyThickness = enemy.Margin;
if (direction == '1')
{
enemyThickness.Left -= xChange;
}
if (direction == '0')
{
enemyThickness.Left += xChange;
}
enemy.Margin = enemyThickness;
}
private void GoDown()
{
enemyThickness.Top += yChange;
enemy.Margin = enemyThickness;
}
}
Instead of initializing and assigning event handler in DrawBall method, do that in constructor of EnemyTeam class. This is will give you on timer per EnemyTeam object.
Declare enemyTimer as a static field:
class EnemyTeam
{
private static enemyTimer = new DispatcherTimer();
...
The keyword static will make the field shared for the class.
You're making multiple timers and throwing them away. See this line:
enemyTimer = new DispatcherTimer();
Every time you call that, you're making a new timer and throwing away the previous copy that enemyTimer held a reference to. Because enemyTimer.Start() is called after DrawTeam, it's called only on the last-created timer. None of the other timers get started.
But even if the other timers got started, you'd still only see one Ellipse move, because in enemyTimer_Tick you only ever make changes to enemy, which is a class member variable that points to the last Ellipse created.
I would suggest that you only use one timer, that you save all the Ellipses you create in a list for later use, and that in enemyTimer_Tick you update all of those Ellipses by iterating through the list.
EDIT: Here is a copy of your code, reworked a bit to show you what I mean. I don't really understand what you're trying to do with MoveTeam and the enemyThickness variable, so I didn't mess with that stuff. That is to say, this isn't a complete working solution, just an example of the changes I'm suggesting.
using System.Collections.Generic;
class EnemyTeam
{
private List<Ellipse> enemies = new List<Ellipse>();
private Canvas canvas;
private double xChange = 50, yChange = 50;
public DispatcherTimer enemyTimer;
private char direction = '0';
private Thickness enemyThickness;
public EnemyTeam(Canvas canvas, double startPosition, SolidColorBrush playerBrush)
{
this.canvas = canvas;
DrawTeam(canvas, 40, playerBrush);
enemyTimer = new DispatcherTimer();
enemyTimer.Interval = TimeSpan.FromMilliseconds(100);
enemyTimer.Tick += enemyTimer_Tick;
enemyTimer.Start();
}
private void DrawBall(SolidColorBrush brush, Canvas canvas,double x,double y)
{
enemy = new Ellipse();
enemy.Stroke = brush;
enemy.Fill = brush;
enemy.Height = 30;
enemy.Width = 30;
enemy.Margin = new Thickness(x,y, 0, 0);
enemyThickness = enemy.Margin; // what is this supposed to do?
canvas.Children.Add(enemy);
enemies.Add(enemy);
}
void enemyTimer_Tick(object sender, EventArgs e)
{
foreach (Ellipse enemy in enemies)
{
if (enemyThickness.Left >= canvas.Width - 100)
{
GoDown();
direction = '1';
}
if (enemyThickness.Left <= 0 + 20)
{
GoDown();
direction = '0';
}
MoveTeam(enemy);
}
}
private void MoveTeam(Ellipse enemy)
{
enemyThickness = enemy.Margin;
if (direction == '1')
{
enemyThickness.Left -= xChange;
}
if (direction == '0')
{
enemyThickness.Left += xChange;
}
enemy.Margin = enemyThickness;
}
private void GoDown()
{
enemyThickness.Top += yChange;
enemy.Margin = enemyThickness;
}
}

How to move panels up/down on keysDown event in c#

I've 4 panels, having same Y and different X, that are created at the program start on a picturebox. When I click on a panel, it sets the focus and is ready to get a keysDown event so i.e. if I click on up arrow key the panel moves up.
This is the code:
public partial class FormView : Form
{
List<CircleButton> myPanels = new List<CircleButton>(); // array of panels CircleButton
Point[] arrayPoints_milestones; // array of X,Y
int index;
public FormView()
{
InitializeComponent();
arrayPoints_milestones = new Point[4];
for (int i = 0; i < 4; i++ )
{
arrayPoints_milestones[i] = new Point { X = 20, Y = 20 };
}
test();
}
protected void panel_Click(object sender, EventArgs e)
{
myPanels[index].PreviewKeyDown -= new PreviewKeyDownEventHandler(panel_KeyDown);
CircleButton panel = sender as CircleButton;
index = (int)panel.Tag;
myPanels[index].Focus(); //panel.Focus();
myPanels[index].PreviewKeyDown += new PreviewKeyDownEventHandler(panel_KeyDown);
}
private void panel_KeyDown(object sender, PreviewKeyDownEventArgs e)
{
if (e.KeyCode == Keys.Up)
{
myPanels[index].Centre = new Point(myPanels[index].Centre.X, myPanels[index].Centre.Y - 10);
MessageBox.Show("" + myPanels[index].Centre.Y);
Invalidate();
}
if (e.KeyCode == Keys.Down)
{
myPanels[index].Centre = new Point(myPanels[index].Centre.X, myPanels[index].Centre.Y + 10);
MessageBox.Show("" + myPanels[index].Centre.Y);
Invalidate();
}
}
private void test()
{
//for (int i = 0; i < 4; i++)
int i=0;
foreach(var value in arrayPoints_milestones)
{
CircleButton panel = new CircleButton();
panel.Tag = i;
panel.Centre = new Point(arrayPoints_milestones[i].X + i * 10, arrayPoints_milestones[i].Y);
panel.Radius = 10;
panel.BackColor = Color.Red;
panel.Message = "Index: " + panel.Tag.ToString();
myPanels.Add(panel); // qui aggiungo il pannello alla lista di pannelli myPanels
pictureBox1.Controls.Add(myPanels[i]);
myPanels[i].Click += new EventHandler(panel_Click);
i++;
}
}
}
and this is the custom panel class:
public class CircleButton : Panel
{
//Properties to draw circle
float radius;
public float Radius
{
get { return radius; }
set
{
radius = value;
this.Size = new Size((int)Radius, (int)Radius);
}
}
public string Name
{
get;
set;
}
Point centre;
public Point Centre
{
get { return centre; }
set
{
centre = value;
this.Location = Centre;
}
}
public string Message { get; set; }
public CircleButton()
{
//Default Values
Name = "panel_base";
this.BackColor = Color.Black;
Radius = 1;
Centre = new Point(0, 0);
this.DoubleBuffered = true;
}
protected override void OnPaint(PaintEventArgs e)
{
base.OnPaint(e);
//Defines a graphic path and set it as the panel's region
//For custom region use different path's
if (centre != null)
{
GraphicsPath path = new GraphicsPath();
path.AddEllipse(0, 0, radius, radius);
this.Region = new Region(path);
path.Dispose();
}
}
}
Each time you click a panel, a PreviewKeyDownEventHandler is added - so 3 clicks will trigger 3 (different) eventhandlers with the same invocation target, and each will move your panel for 10 pixels up/down:
protected void panel_Click(object sender, EventArgs e) {
CircleButton panel = sender as CircleButton;
index = (int)panel.Tag;
myPanels[index].Focus(); //panel.Focus();
myPanels[index].PreviewKeyDown += new PreviewKeyDownEventHandler(panel_KeyDown);
}
Updated code for FormView:
public partial class FormView : Form {
List<CircleButton> myPanels = new List<CircleButton>(); // local use only in my example
Point[] arrayPoints_milestones; //not needed anymore
int index; //not needed anymore
public FormView() {
InitializeComponent();
this.Load += FormView_Load;
}
void FormView_Load(object sender, EventArgs args) {
Point panelOffset = new Point(20, 20);
for (int i = 0; i < 4; i++) {
var panel = new CircleButton() {
Name = "panel" + i, //Attention! You have hidden the property "Name" in "Control" with a re-declaration in "CircleButton"
Tag = i, //not needed anymore, right?
Centre = new Point(panelOffset.X + i * 10, panelOffset.Y),
Radius = 10,
BackColor = Color.Red,
Message = "Index: " + i.ToString(),
};
panel.Click += (s, e) => {
panel.Focus();
};
panel.PreviewKeyDown += (s, e) => {
if(e.KeyCode == Keys.Up) {
Point centre = panel.Centre; //copy value
centre.Y -= 10;
panel.Centre = centre; //assign modified copy
Invalidate();
}
if(e.KeyCode == Keys.Down) {
Point centre = panel.Centre; //copy value
centre.Y += 10;
panel.Centre = centre; //assign modified copy
Invalidate();
}
};
myPanels.Add(panel);
pictureBox1.Controls.Add(panel);
}
}
}

System.InvalidOperationException in C# WPF

I want to move a rectangle in WPF application using the following code. However, I am getting the following error:
System.InvalidOperationException: Cannot use a DependencyObject that belongs to a different thread
I looked at other problems in stackoverflow but nothing worked.
public partial class MainWindow : Window
{
private Rectangle rect;
int count = 1;
Timer timer;
public MainWindow()
{
InitializeComponent();
Rectangle movedRectangle = new Rectangle();
movedRectangle.Width = 200;
movedRectangle.Height = 50;
movedRectangle.Fill = Brushes.Blue;
movedRectangle.Opacity = 0.5;
TranslateTransform translateTransform1 = new TranslateTransform(50, 20);
movedRectangle.RenderTransform = translateTransform1;
this.can.Children.Add(movedRectangle);
this.rect = movedRectangle;
timer = new Timer(500);
timer.Elapsed += OnTimedEvent;
timer.Enabled = true;
}
private void OnTimedEvent(Object source, ElapsedEventArgs e)
{
count++;
TranslateTransform translateTransform1 = new TranslateTransform(50 + count * 2, 20);
this.rect.Dispatcher.Invoke(new Action(()=>
rect.RenderTransform = translateTransform1));
//this.can.UpdateLayout();
this.can.Dispatcher.Invoke(new Action(()=>
this.can.UpdateLayout()
));
}
I would suggest you to use DispatcherTimer than a normal timer.
Please see the below solution. enjoy.
Note: for DispatcherTimer you will need to add the assembly reference for System.Windows.Threading
public partial class MainWindow : Window
{
private Rectangle rect;
int count = 1;
private DispatcherTimer timer = null;
public MainWindow()
{
InitializeComponent();
Rectangle movedRectangle = new Rectangle();
movedRectangle.Width = 200;
movedRectangle.Height = 50;
movedRectangle.Fill = Brushes.Blue;
movedRectangle.Opacity = 0.5;
TranslateTransform translateTransform1 = new TranslateTransform(50, 20);
movedRectangle.RenderTransform = translateTransform1;
this.can.Children.Add(movedRectangle);
this.rect = movedRectangle;
timer = new DispatcherTimer();
timer.Interval = new TimeSpan(0, 0, 0, 0, 500);
timer.Tick += timer_Tick;
timer.Start();
timer.IsEnabled = true;
}
void timer_Tick(object sender, EventArgs e)
{
count++;
TranslateTransform translateTransform1 = new TranslateTransform(50 + count * 2, 20);
Dispatcher.BeginInvoke(new Action<TranslateTransform>(delegate(TranslateTransform t1)
{
rect.RenderTransform = t1;
this.can.UpdateLayout();
}), System.Windows.Threading.DispatcherPriority.Render, translateTransform1);
}
}
You are constructing a TranslateTransform (which is a DependencyObject) outside the UI thread. Easy fix:
this.rect.Dispatcher.Invoke(new Action(
() =>
{
TranslateTransform translateTransform1 = new TranslateTransform(50 + count * 2, 20);
rect.RenderTransform = translateTransform1;
}));
Arguably a better fix: use a DispatcherTimer instead and get rid of all your Dispatcher.Invoke calls.

Why does the WPF storyboard stops after a few cycles?

I have a canvas where I draw rectangles and move them randomly with the help of a storyboard. After a few cycles the storyboard.completed event does not fire any more. Does anybody know? here is my xaml:
<Grid>
<Canvas Name="movingCanvas" Background="Green" Margin="0,29,0,0"></Canvas>
<TextBlock Height="23" Name="textBlock1" Text="TextBlock" Margin="528,0,0,538" />
</Grid>
And the code:
private Random random = new Random();
private Storyboard gameLoop = new Storyboard();
private int i = 0;
public Window3()
{
InitializeComponent();
this.gameLoop.Duration = TimeSpan.FromMilliseconds(100);
this.gameLoop.Completed += new EventHandler(this.gameLoop_Completed);
this.gameLoop.Begin();
}
private void gameLoop_Completed(object sender, EventArgs e)
{
this.addRectangle();
this.moveRectangle();
i++;
this.textBlock1.Text = i.ToString();
this.gameLoop.Begin();
}
private void addRectangle()
{
Rectangle rect = new Rectangle();
rect.Height = 100;
rect.Width = 100;
rect.Stroke = new SolidColorBrush(Colors.Black);
Canvas.SetLeft(rect, random.Next((int)this.Width));
Canvas.SetTop(rect, random.Next((int)this.Height));
this.movingCanvas.Children.Add(rect);
}
private void moveRectangle()
{
foreach (UIElement elm in this.movingCanvas.Children)
{
int moveLeft = random.Next(10);
int distance = random.Next(-10, 20);
if (moveLeft > 5)
{
Canvas.SetTop(elm, Canvas.GetTop(elm) + distance);
}
else
{
Canvas.SetLeft(elm, Canvas.GetLeft(elm) + distance);
}
}
}
The Completed event does also not occur whitout creating and moving rectangles:
private Storyboard gameLoop = new Storyboard();
private int i = 0;
public Window3()
{
InitializeComponent();
this.gameLoop.Duration = TimeSpan.FromMilliseconds(100);
this.gameLoop.Completed += new EventHandler(this.gameLoop_Completed);
this.gameLoop.Begin();
}
private void gameLoop_Completed(object sender, EventArgs e)
{
i++;
this.textBlock1.Text = i.ToString();
this.gameLoop.Begin();
}
If you add a animation to the storyboard, the storyboard not stops firing the event.
public Window3()
{
InitializeComponent();
this.gameLoop.Duration = TimeSpan.FromMilliseconds(100);
this.gameLoop.Completed += new EventHandler(this.gameLoop_Completed);
DoubleAnimation animation= new DoubleAnimation { From = 100, To = 101 };
ani.SetValue(Storyboard.TargetProperty, this);
ani.SetValue(Storyboard.TargetPropertyProperty, new PropertyPath("Height"));
this.gameLoop.Children.Add(ani);
this.gameLoop.Begin();
}
Like Kshitij Mehta said above, i think use a timer instead the storyboard, but maybe you have a reason to use a storyboard....
Do you really mean to add a new rectangle on every iteration of the loop?
You'll very quickly get tens of thousands if not millions of rectangles which will take longer and longer to draw.

Categories

Resources