I made a small WPF application to slide UserControls in and out, the problem I have is when a UserControl animated to slide in, then I click the button to slide another UserControl in, they both slide out - I'm not sure why this is?
public UserControl1()
{
InitializeComponent();
}
public void SlideIn(UserControl uc)
{
ThicknessAnimation tAnimation = new ThicknessAnimation();
tAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.5));
tAnimation.From = new Thickness(500, 0, -500, 0);
tAnimation.To = new Thickness(0);
tAnimation.DecelerationRatio = 0.9;
Storyboard.SetTargetName(tAnimation, uc.Name);
Storyboard.SetTargetProperty(tAnimation, new PropertyPath(MarginProperty));
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(tAnimation);
storyboard.Begin(uc);
this.Content = uc;
}
public void SlideOut(UserControl uc)
{
ThicknessAnimation tAnimation = new ThicknessAnimation();
tAnimation.Duration = new Duration(TimeSpan.FromSeconds(0.5));
tAnimation.To = new Thickness(-500, 0, 500, 0);
tAnimation.DecelerationRatio = 0.9;
Storyboard.SetTargetName(tAnimation, uc.Name);
Storyboard.SetTargetProperty(tAnimation, new PropertyPath(MarginProperty));
Storyboard storyboard = new Storyboard();
storyboard.Children.Add(tAnimation);
storyboard.Begin(this);
}
private void button1_Click(object sender, RoutedEventArgs e)
{
SlideOut(userControl1);
UserControl2 uc2 = new UserControl2();
SlideIn(uc2);
}
Do you set the Name property of the UserControl somewhere? Or to be more precise, do you give the second UserControl a different Name than the first one? Your animations get their target set by
Storyboard.SetTargetName(tAnimation, uc.Name);
so names should be different. Alternatively you may call
Storyboard.SetTarget(tAnimation, uc);
to specify the target.
Related
I create a stackpanel, and put some controls and 1 of these is a textbox, programaticly.
How can i create an event that, when i click on textbox i delete the stackpanel and everything inside?
Here is my code...
System.Windows.Controls.StackPanel Defesa = new StackPanel();
Defesa.Height = 120;
Defesa.Width = 140;
Panel_DE.Children.Add(Defesa);
Defesa.Background = new
SolidColorBrush((Color)ColorConverter.
ConvertFromString("#FF000000"));
Defesa.Margin = new Thickness(20, 0, 0, 0);
Ellipse Foto = new Ellipse();
Foto.Height = 80;
Foto.Width = 80;
Foto.StrokeThickness = 2;
SolidColorBrush borda = new SolidColorBrush();
borda.Color = Colors.White; ;
Foto.Stroke = borda;
Defesa.Children.Add(Foto);
ImageBrush camera = new ImageBrush();
camera.ImageSource = new BitmapImage(new
Uri(#"C:\Users\Vitor\documents\visual studio 2013\Projects\Manager
Treinador\Manager Treinador\Icons\photo-camera w.png"));
Foto.Fill = camera;
System.Windows.Controls.TextBlock Nome_def = new TextBlock();
Nome_def.Text = def_name;
Nome_def.Foreground = new
SolidColorBrush((Color)ColorConverter.ConvertFromString
("#FFF9F4F4"));
Nome_def.HorizontalAlignment = HorizontalAlignment.Center;
Defesa.Children.Add(Nome_def);
System.Windows.Controls.StackPanel Panel = new StackPanel();
Panel.Orientation = Orientation.Horizontal;
Defesa.Children.Add(Panel);
System.Windows.Controls.TextBlock But_Delet = new TextBlock();
But_Delet.Text = "X";
But_Delet.FontWeight = FontWeights.Bold;
But_Delet.Foreground = new
SolidColorBrush((Color)ColorConverter.ConvertFromString
("#FFF90707"));
Panel.Children.Add(But_Delet);
But_Delet.HorizontalAlignment = HorizontalAlignment.Left;
But_Delet.Cursor = Cursors.Hand;
But_Delete is the text box that i want to remove all...
Thanks
Since a TextBlock does not have a click event, you will need to simulate this by using OnPreviewMouseDown event. To do this:
add this to the end of your code:
But_Delet.PreviewMouseDown += ButDeletOnPreviewMouseDown;
Then add this event handler:
private void ButDeletOnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
Panel_DE.Children.Remove(Defesa);
}
However, if there is a chance you will need to restore these controls, it would better to hide them using this event handler instead:
private void ButDeletOnPreviewMouseDown(object sender, MouseButtonEventArgs e)
{
Defesa.Visibility = Visibility.Hidden;
}
I have been able to do the above with the following code in my subclassed TabItem:
protected override void OnSelected(RoutedEventArgs e)
{
base.OnSelected(e);
if (this.StoryBoard == null)
{
ColorAnimation anim = new ColorAnimation(Colors.Transparent, Colors.AliceBlue, new Duration(TimeSpan.FromSeconds(1)))
{
AutoReverse = true,
RepeatBehavior = RepeatBehavior.Forever
};
Storyboard.SetTarget(anim, this);
Storyboard.SetTargetProperty(anim, new PropertyPath("Background.Color"));
Storyboard sb = new Storyboard();
sb.Children.Add(anim);
this.StoryBoard = sb;
}
VisualTree.FindParent<OMWTabControl>(this).Items.Cast<OMWTabItem>().ToList().ForEach(n =>
{
if (n.StoryBoard != null)
{
n.StoryBoard.Stop();
}
});
this.StoryBoard.Begin();
}
I know I am butchering the correct way to do this - I should be using DataTriggers I believe with Setters.
I have done extensive searching and it's all in XAML which is mostly intrepretable into C#, but not all.
Can someone point me to the "correct" way to do this in code behind?
Whenever you want to know about any methods, interfaces, classes, or just about anything about the .NET Framework, just go to MSDN. You could have gone to the Storyboard.TargetProperty Attached Property page on MSDN for a super quick answer to your question. From the linked page:
public StoryboardExample()
{
// Create a name scope for the page.
NameScope.SetNameScope(this, new NameScope());
this.WindowTitle = "Animate Properties using Storyboards";
StackPanel myStackPanel = new StackPanel();
myStackPanel.MinWidth = 500;
myStackPanel.Margin = new Thickness(30);
myStackPanel.HorizontalAlignment = HorizontalAlignment.Left;
TextBlock myTextBlock = new TextBlock();
myTextBlock.Text = "Storyboard Animation Example";
myStackPanel.Children.Add(myTextBlock);
//
// Create and animate the first button.
//
// Create a button.
Button myWidthAnimatedButton = new Button();
myWidthAnimatedButton.Height = 30;
myWidthAnimatedButton.Width = 200;
myWidthAnimatedButton.HorizontalAlignment = HorizontalAlignment.Left;
myWidthAnimatedButton.Content = "A Button";
// Set the Name of the button so that it can be referred
// to in the storyboard that's created later.
// The ID doesn't have to match the variable name;
// it can be any unique identifier.
myWidthAnimatedButton.Name = "myWidthAnimatedButton";
// Register the name with the page to which the button belongs.
this.RegisterName(myWidthAnimatedButton.Name, myWidthAnimatedButton);
// Create a DoubleAnimation to animate the width of the button.
DoubleAnimation myDoubleAnimation = new DoubleAnimation();
myDoubleAnimation.From = 200;
myDoubleAnimation.To = 300;
myDoubleAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(3000));
// Configure the animation to target the button's Width property.
Storyboard.SetTargetName(myDoubleAnimation, myWidthAnimatedButton.Name);
Storyboard.SetTargetProperty(myDoubleAnimation, new PropertyPath(Button.WidthProperty));
// Create a storyboard to contain the animation.
Storyboard myWidthAnimatedButtonStoryboard = new Storyboard();
myWidthAnimatedButtonStoryboard.Children.Add(myDoubleAnimation);
// Animate the button width when it's clicked.
myWidthAnimatedButton.Click += delegate(object sender, RoutedEventArgs args)
{
myWidthAnimatedButtonStoryboard.Begin(myWidthAnimatedButton);
};
myStackPanel.Children.Add(myWidthAnimatedButton);
//
// Create and animate the second button.
//
// Create a second button.
Button myColorAnimatedButton = new Button();
myColorAnimatedButton.Height = 30;
myColorAnimatedButton.Width = 200;
myColorAnimatedButton.HorizontalAlignment = HorizontalAlignment.Left;
myColorAnimatedButton.Content = "Another Button";
// Create a SolidColorBrush to paint the button's background.
SolidColorBrush myBackgroundBrush = new SolidColorBrush();
myBackgroundBrush.Color = Colors.Blue;
// Because a Brush isn't a FrameworkElement, it doesn't
// have a Name property to set. Instead, you just
// register a name for the SolidColorBrush with
// the page where it's used.
this.RegisterName("myAnimatedBrush", myBackgroundBrush);
// Use the brush to paint the background of the button.
myColorAnimatedButton.Background = myBackgroundBrush;
// Create a ColorAnimation to animate the button's background.
ColorAnimation myColorAnimation = new ColorAnimation();
myColorAnimation.From = Colors.Red;
myColorAnimation.To = Colors.Blue;
myColorAnimation.Duration = new Duration(TimeSpan.FromMilliseconds(7000));
// Configure the animation to target the brush's Color property.
Storyboard.SetTargetName(myColorAnimation, "myAnimatedBrush");
Storyboard.SetTargetProperty(myColorAnimation, new PropertyPath(SolidColorBrush.ColorProperty));
// Create a storyboard to contain the animation.
Storyboard myColorAnimatedButtonStoryboard = new Storyboard();
myColorAnimatedButtonStoryboard.Children.Add(myColorAnimation);
// Animate the button background color when it's clicked.
myColorAnimatedButton.Click += delegate(object sender, RoutedEventArgs args)
{
myColorAnimatedButtonStoryboard.Begin(myColorAnimatedButton);
};
myStackPanel.Children.Add(myColorAnimatedButton);
this.Content = myStackPanel;
}
Please visit the linked page for further information.
I want a resizing animation when stackpanel visibility is set to visible state, but instead of that, I'm getting neverending flickering of border containing stackpanel.I don't think I'm doing it wrong.
Stack panel contains an instance of TextBlock.
private void MyBorder_SizeChanged_1(object sender, SizeChangedEventArgs e)
{
if (!first)
{
DoubleAnimation anim = new DoubleAnimation();
anim.From = e.PreviousSize.Height;
anim.To = e.NewSize.Height;
anim.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTarget(anim, MyBorder);
Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
Storyboard st = new Storyboard();
st.Children.Add(anim);
st.Begin();
}
first = false;
}
private void MyBorder_Tap_1(object sender, GestureEventArgs e)
{
if (MyPanel.Visibility == Visibility.Collapsed)
MyPanel.Visibility = Visibility.Visible;
else
MyPanel.Visibility = Visibility.Collapsed;
}
The problem is that when you animate the height of the border it will trigger the SizeChanged event so you have a loop: size changed event>animate height>size changed event> ..
Also when the sized changed event is fired, the size change has already taken placed so even if that was working you will get a little flicking when it go back to do the animation.
Finally using HEight in an animation force a rendering update so that is not hardware accelerated.
Probably the best would be to either do a Translate Transform or a Scale Transform.
For exemple you could do a scale transform between 0 and 1 directly on MyPanel in the tap event.
This might help you to. It is a work around
private void MyBorder_SizeChanged_1(object sender, SizeChangedEventArgs e)
{
if (!first)
{
DoubleAnimation anim = new DoubleAnimation();
anim.From = e.PreviousSize.Height;
anim.To = e.NewSize.Height;
anim.Duration = new Duration(TimeSpan.FromSeconds(1));
Storyboard.SetTarget(anim, MyBorder);
Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
Storyboard st = new Storyboard();
st.Children.Add(anim);
st.Completed += st_Completed;
MyBorder.SizeChanged -= MyBorder_SizeChanged_1;
st.Begin();
}
first = false;
}
void st_Completed(object sender, EventArgs e)
{
MyBorder.SizeChanged += MyBorder_SizeChanged_1;
}
private void MyBorder_Tap_1(object sender, GestureEventArgs e)
{
if (MyPanel.Visibility == Visibility.Collapsed)
MyPanel.Visibility = Visibility.Visible;
else
MyPanel.Visibility = Visibility.Collapsed;
}
With reference to the fact that border is getting resized even in the storyboard its better to remove the event of size changed. Try animating the parent container on chld size changed some thing kind of this
I've solved this problem. Silly my, I thought that Measure method of StackPanel is private, and didn't bother to make sure about it, here's solution code for expanding StackPanel on Click.
private void MyBorder_Tap_1(object sender, GestureEventArgs e)
{
if (MyPanel.Visibility == Visibility.Collapsed)
{
MyPanel.Visibility = Visibility.Visible;
MyPanel.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
DoubleAnimation anim = new DoubleAnimation();
anim.From = MyBorder.ActualHeight;
anim.To = MyBorder.ActualHeight + MyPanel.DesiredSize.Height;
anim.Duration = new Duration(TimeSpan.FromSeconds(0.25));
Storyboard.SetTarget(anim, MyBorder);
Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
Storyboard st = new Storyboard();
st.Children.Add(anim);
st.Begin();
}
else
{
MyPanel.Measure(new Size(Double.PositiveInfinity, Double.PositiveInfinity));
DoubleAnimation anim = new DoubleAnimation();
anim.From = MyBorder.ActualHeight;
anim.To = MyBorder.ActualHeight - MyPanel.DesiredSize.Height;
anim.Duration = new Duration(TimeSpan.FromSeconds(0.25));
Storyboard.SetTarget(anim, MyBorder);
Storyboard.SetTargetProperty(anim, new PropertyPath(Border.HeightProperty));
Storyboard st = new Storyboard();
st.Children.Add(anim);
st.Completed += (a,b) => { MyPanel.Visibility = Visibility.Collapsed; };
st.Begin();
}
}
I have two main pages, GamePage (where all the code to play the game is in), and Mainpage (which is the title screen). What I want to be able to do is play music on the title screen (mainpage.xaml)
I have tried using the content.load method like I have done in the gamepage.xaml. But that does not work, it comes up with a null exception. I have also tried putting it in the section you can see in the screenshot entitled MazeEscapePhoneSilveright, but when i try to run it; the error unexpected characters in the sound file comes up.
How can I play music on the mainpage.xaml, nothing I've tried seems to:
Codebehind mainpage.xaml:
public partial class MainPage : PhoneApplicationPage
{
// Constructor
ContentManager contentManager;
MediaElement player = null;
Popup nameEntry = new Popup();
bool gameMusic;
bool mazeStart = true;
TextBox txtNameEntry = new TextBox();
SoundEffect theme_music;
SoundEffectInstance theme_music_Instance;
SoundEffect zap;
SoundEffectInstance zapInstance;
public MainPage()
{
InitializeComponent();
//SharedGraphicsDeviceManager.Current.GraphicsDevice.SetSharingMode(true);
//Plays the music through a mediaplayer, and a public boolean value.
if (App.Current.Resources.Contains("mediaPlayer"))
{
player = App.Current.Resources["mediaPlayer"] as MediaElement;
player.Source = new Uri("./MazeEscapePhoneSilverightLibContent/Media/magic_wav_file", UriKind.Relative);
}
gameMusic = ((App)Application.Current).gameMusic;
if (gameMusic) player.Play();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (((App)Application.Current).gameMusic)
{
//theme_music = this.contentManager.Load<SoundEffect>("Media/magic_wav_file");
//theme_music_Instance = theme_music.CreateInstance();
}
}
//method runs when "Start Game" button is pressed
private void btnStartGame_Click(object sender, RoutedEventArgs e)
{
if (gameMusic)
{
player.Play();
}
#region CREATE AND DISPLAY POP UP
Border border = new Border();
border.BorderBrush = new SolidColorBrush(Colors.White);
border.BorderThickness = new Thickness(10);
StackPanel myStackPanel = new StackPanel();
myStackPanel.Background = new SolidColorBrush(Colors.Black);
//Textblock containing the name you input and its properties.
//txtNameEntry.Text = Microsoft.Phone.Info.DeviceExtendedProperties.GetValue("DeviceName").ToString();
txtNameEntry.Text = "Player 1";
txtNameEntry.Width = 350;
txtNameEntry.Height = 100;
txtNameEntry.MaxLength = 10;
txtNameEntry.FontFamily = new FontFamily("Comis Sans MS");
txtNameEntry.FontSize = 48.0;
txtNameEntry.Foreground = new SolidColorBrush(Colors.Orange);
txtNameEntry.Background = new SolidColorBrush(Colors.LightGray);
txtNameEntry.BorderBrush = new SolidColorBrush(Colors.LightGray);
//The ok button, which then allows you to procede into the game.
Button btnNameEntryOK = new Button();
btnNameEntryOK.Content = "Ok";
btnNameEntryOK.Background = new SolidColorBrush(Colors.Orange);
btnNameEntryOK.FontFamily = new FontFamily("Comic Sans Ms");
btnNameEntryOK.FontSize = 25.0;
btnNameEntryOK.Width = 180;
btnNameEntryOK.Height = 70;
btnNameEntryOK.Click += new RoutedEventHandler(btnNameEntryOK_Click);
btnNameEntryOK.Margin = new Thickness(10);
//Place these in the order you want them to be renderd to the screen.
myStackPanel.Children.Add(txtNameEntry);
myStackPanel.Children.Add(btnNameEntryOK);
border.Child = myStackPanel;
nameEntry.Child = border;
//set screen position of pop up
nameEntry.VerticalOffset = 100.0;
nameEntry.HorizontalOffset = 50.0;
//open pop up
nameEntry.IsOpen = true;
#endregion
if (nameEntry.IsOpen == false && mazeStart == true)
{
player.Stop();
}
}
void btnNameEntryOK_Click(object sender, RoutedEventArgs e)
{
((App)Application.Current).playerName = txtNameEntry.Text;
nameEntry.IsOpen = false;
mazeStart = true;
player.Stop();
NavigationService.Navigate(new Uri("/GamePage.xaml", UriKind.Relative));
}
private void btnOptions_Click(object sender, RoutedEventArgs e)
{
nameEntry.IsOpen = false;
NavigationService.Navigate(new Uri("/Options.xaml", UriKind.Relative));
}
Screenshot of the solution explorer:
I have a button containing an image, and I want that image rotates while some code is executed, then stop at the end of this processing.
My code almost works if I begin the storyboard, but when I add the line sb.Stop(), the animation never begins.
Here is my code:
private void refreshPostIt(int postItIndex)
{
Button btn = // Button to rotate
Storyboard sb = new Storyboard();
DoubleAnimation rotate = new DoubleAnimation();
rotate.From = 0;
rotate.To = 360;
rotate.RepeatBehavior = RepeatBehavior.Forever;
RotateTransform rt = new RotateTransform();
btn.RenderTransformOrigin = new Point(0.5, 0.5);
btn.RenderTransform = rt;
Storyboard.SetTarget(rotate, btn);
Storyboard.SetTargetName(rotate, btn.Name);
Storyboard.SetTargetProperty(rotate, new PropertyPath("(UIElement.RenderTransform).(RotateTransform.Angle)"));
sb.Children.Add(rotate);
sb.Begin(this, true);
// Some code which can take several seconds
sb.Stop();
}
I'm stuck.
I have a solution that works for me.
private void refreshPostIt()
{
// Button btn; is defined somewhere else
Storyboard sb = new Storyboard();
DoubleAnimation rotate = new DoubleAnimation();
rotate.From = 0;
rotate.To = 360;
rotate.RepeatBehavior = RepeatBehavior.Forever;
RotateTransform rt = new RotateTransform();
btn.RenderTransformOrigin = new Point(0.5, 0.5);
btn.RenderTransform = rt;
Storyboard.SetTarget(rotate, btn);
Storyboard.SetTargetName(rotate, btn.Name);
Storyboard.SetTargetProperty(rotate, new PropertyPath("(UIElement.RenderTransform).(RotateTransform.Angle)"));
sb.Children.Add(rotate);
sb.Begin(btn, true);
// Do your stuff here (Not in the UI Thread)
// Maybe use a semaphore to lock the sb.Stop(btn)
sb.Stop(btn);
}
whole example code:
public partial class Window1 : Window
{
Button btn;
Storyboard sb;
public Window1()
{
btn = new Button();
InitializeComponent();
this.grid.Children.Add(btn);
refreshPostIt();
}
private void refreshPostIt()
{
// Button btn; is defined somewhere else
sb = new Storyboard();
DoubleAnimation rotate = new DoubleAnimation();
rotate.From = 0;
rotate.To = 360;
rotate.RepeatBehavior = RepeatBehavior.Forever;
RotateTransform rt = new RotateTransform();
btn.RenderTransformOrigin = new Point(0.5, 0.5);
btn.RenderTransform = rt;
Storyboard.SetTarget(rotate, btn);
Storyboard.SetTargetName(rotate, btn.Name);
Storyboard.SetTargetProperty(rotate, new PropertyPath("(UIElement.RenderTransform).(RotateTransform.Angle)"));
sb.Children.Add(rotate);
sb.Begin(btn, true);
BackgroundWorker asd = new BackgroundWorker();
asd.DoWork += new DoWorkEventHandler(asd_DoWork);
asd.RunWorkerCompleted += new RunWorkerCompletedEventHandler(asd_RunWorkerCompleted);
asd.RunWorkerAsync();
}
void asd_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e)
{
if (sb != null)
{
sb.Stop(btn);
}
}
void asd_DoWork(object sender, DoWorkEventArgs e)
{
Thread.Sleep(2000);
}
}
Ok, I want to explain what I think is your problem here. When you use the UI-Thread to do your "work" it can't update your UI and though won't animate the rotating, when its done with your "work", between starting and stopping the animation, and finally would have time to update the UI, you call to stop animating. That leads to not showing any animation. You need to put your work in a different thread to prevent this from happening.
Hope that helps.