I'm learning wpf and at the same time developing an app with it. I'm having a hard time figuring out how i can run something when a doubleanimation (Or other sorts) is done. For instance:
DoubleAnimation myanim = new DoubleAnimation();
myanim.From = 10;
myanim.To = 100;
myanim.Duration = new Duration(TimeSpan.FromSeconds(3));
myview.BeginAnimation(Button.OpacityPropert, myanim);
//Code to do something when animation ends
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Windows.Media.Animation;
namespace app
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void button1_Click(object sender, RoutedEventArgs e)
{
DoubleAnimation widthbutton = new DoubleAnimation();
widthbutton.From = 55;
widthbutton.To = 100;
widthbutton.Duration = new Duration(TimeSpan.FromSeconds(1.5));
button1.BeginAnimation(Button.HeightProperty, widthbutton);
DoubleAnimation widthbutton1 = new DoubleAnimation();
widthbutton1.From = 155;
widthbutton1.To = 200;
widthbutton1.Duration = new Duration(TimeSpan.FromSeconds(1.5));
button1.BeginAnimation(Button.WidthProperty, widthbutton1);
widthbutton.Completed += new EventHandler(myanim_Completed);
}
private void myanim_Completed(object sender, EventArgs e)
{
//your completed action here
MessageBox.Show("Animation done!");
}
}
}
How is this accomplishable? I have read quite a few other posts about this, but they all explain it using xaml, however i would like to do it using c# code. Thanks!
You can attach an event handler to the DoubleAnimation's Completed event.
myanim.Completed += new EventHandler(myanim_Completed);
private void myanim_Completed(object sender, EventArgs e)
{
//your completed action here
}
Or, if you prefer it inline, you can do
myanim.Completed += (s,e) =>
{
//your completed action here
};
Remember to attach the handler before starting the animation otherwise it won't fire.
Related
I'm writing an app that displays your current hashrate in Ethereum (A cryptocurrency like Bitcoin), and I need to somehow get the continuous output from the Command line that is running. This is what I have so far, but it is not printing to the program output:
pProcess.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
// Prepend line numbers to each line of the output.
if (!String.IsNullOrEmpty(e.Data))
{
System.Console.Write(e.Data);
}
});
//Wait for process to finish
pProcess.WaitForExit();
What is not working with this code? I'm guessing there's something messed up with the event handler, but I don't know what.
Copy and paste it to your code I modified it for you:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.Diagnostics;
namespace ETHMinerVisualiser
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void MineButton_Click(object sender, RoutedEventArgs e)
{
Task.Run(() => { startMining(); });
}
public void startMining()
{
//Create process
System.Diagnostics.Process pProcess = new System.Diagnostics.Process();
//strCommand is path and file name of command to run
pProcess.StartInfo.FileName = #"E:/Documents/ETH/ETHMinerVisualiser/ethminer-cuda-0.9.41-new/ethminer.exe";
//strCommandParameters are parameters to pass to program
pProcess.StartInfo.Arguments = "-F eu1.ethermine.org:5555/0x9c3f6281b123541f10c9bf37a8f273aa2a774d17.PCGPU -C";
pProcess.StartInfo.UseShellExecute = false;
//Set output of program to be written to process output stream
pProcess.StartInfo.RedirectStandardOutput = true;
//Optional
pProcess.StartInfo.WorkingDirectory = "";
//Start the process
pProcess.Start();
//pProcess.StartInfo.CreateNoWindow = true;
//pProcess.BeginOutputReadLine();
pProcess.OutputDataReceived += new DataReceivedEventHandler((sender, e) =>
{
// Prepend line numbers to each line of the output.
if (!String.IsNullOrEmpty(e.Data))
{
//System.Console.Write(e.Data);
Debug.WriteLine(e.Data);
}
});
//Wait for process to finish
pProcess.BeginOutputReadLine();
pProcess.WaitForExit();
}
}
}
I managed to get into learning how to make phone apps. I'm completely new to c# and xaml. But I have done visual basic to a basic knowledge.
I am trying to recreate my project in the windows phone and I've got the basic progress bar in a timer but when the timer has reached it's end I want it to navigate to a new page which I have created. I have seen many different examples but none have helped It either doesn't work or has an error.
This is the code so far on the MainPage:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using System.Windows.Threading;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using ProgramOSMobile.Resources;
namespace ProgramOSMobile
{
public partial class MainPage : PhoneApplicationPage
{
private DispatcherTimer timer;
private int i, j;
public MainPage()
{
InitializeComponent();
timer = new DispatcherTimer();
timer.Tick += timer_tick;
Init();
timer.Start();
}
private void Init()
{
j = i = Convert.ToInt32(3);
timer.Interval = TimeSpan.FromMilliseconds(i);
}
private void timer_tick(object sender, EventArgs e)
{
progressBar1.Value = i;
i = i + j;
if (i == 1010)
{
timer.Stop();
}
}
}
}
This all works, but when it comes to using this code for example:
NavigationService.Navigate(new Uri("/LoginScreen.xaml", UriKind.Relative));
Or indeed this new one for the Phone 8.1:
this.Frame.Navigate(typeof(LoginScreen));
I get an error on the 'Frame' part.
Sorry for the really long question but it's just really confusing me.
Thanks,
Dan
As I can see you are using Windows Phone 8.1 Silverlight project and error you are having is used in WinRT version. Here is code for navigation after timer.
for WinRT
protected override void OnNavigatedTo(NavigationEventArgs e)
{
var timer = new DispatcherTimer() { Interval = TimeSpan.FromMilliseconds(300) };
timer.Start();
timer.Tick += ((ax, by) =>
{
timer.Stop();
Loader.IsActive = false;
this.Frame.Navigate(typeof(HomePage));
});
}
and for Silverlight project which you are using
public MainPage()
{
InitializeComponent();
Loaded+=MainPage_Loaded;
}
private void MainPage_Loaded(object sender, RoutedEventArgs e)
{
var timer = new System.Windows.Threading.DispatcherTimer();
timer.Interval = TimeSpan.FromSeconds(2);
timer.Start();
timer.Tick += ((ax, by) => { timer.Stop();
NavigationService.Navigate(new Uri("/Source Code/Recieve.xaml", UriKind.RelativeOrAbsolute));
});
}
You are using Init method for initialization of timer and you can do it fixed I did or dynamic as you like. If any error is thrown then check exception in output it maybe because of Xaml error on next page i.e. HomePage. Hope it helps.
The following code worked for me .. Try it out
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using System.Windows.Threading;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Shell;
using ProgramOSMobile.Resources;
namespace ProgramOSMobile
{
public partial class MainPage : PhoneApplicationPage
{
DispatcherTimer timer = new DispatcherTimer();
int tick=0;
public MainPage()
{
InitializeComponent();
timer.Interval = TimeSpan.FromSeconds(0.5);
timer.Start();
timer.Tick += new EventHandler(splash);
}
private void splash(object sender, EventArgs e)
{
tick++;
if(tick==5){
NavigationService.Navigate(new Uri("/Menu.xaml", UriKind.Relative));
}
}
}
}
The above code has a timer interval of 0.5 seconds and time tick rate of 1
I am currently trying to display and play an animated gif in WPF without much luck
I have tried all the solutions found here including the one in the question
Here is what i currently have
<Window x:Class="Sooooothing.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:Attached="clr-namespace:Sooooothing"
Title="MainWindow" Height="327.861" Width="525">
<Grid>
<MediaElement x:Name="gif" MediaEnded="myGif_MediaEnded" UnloadedBehavior="Manual"
Source="Images\7c6516d73fc8643abf1df969fcc1a72c.gif"
LoadedBehavior="Play" Stretch="None"/>
</Grid>
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Sooooothing
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
//gif.Play();
}
private void myGif_MediaEnded(object sender, RoutedEventArgs e)
{
gif.Position = new TimeSpan(0, 0, 1);
gif.Play();
}
}
}
When the application starts all i get is the white background for the window, at first i though it was the gif not loading but i let it sit for a couple minutes without any change.
Here is my solution
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
namespace Sooooothing
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
GifBitmapDecoder decoder2;
int ImageNumber = 0;
bool mouseIn = true;
double opasity = 0;
List<Thread> threadList = new List<Thread>();
bool programClosed = false;
public MainWindow()
{
InitializeComponent();
Classes.DataHouse.load(); //Im storing all my gif links in this List<string> so i can
// loop through them with buttons on the window
#region thread gif frame changer
Uri myUri = new Uri(Classes.DataHouse.images[ImageNumber], UriKind.RelativeOrAbsolute);
decoder2 = new GifBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource2; // Decode the gif using GifBitmapDecoder then start a thread to
int frameCount = decoder2.Frames.Count;// loop through all the images and put them one after
Thread th = new Thread(() => {// another into an image on your window
while (!programClosed)
{
for (int i = 0; i < frameCount; i++)
{
try{
this.Dispatcher.Invoke(new Action(delegate()
{
frameCount = decoder2.Frames.Count;
if (frameCount >= i)
{
bitmapSource2 = decoder2.Frames[i];
image.Source = bitmapSource2;
}
}));
}
catch
{
//the thread was probably aborted
}
System.Threading.Thread.Sleep(100);
}
}
});
threadList.Add(th);
th.Start();
#endregion
}
private void Window_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton == MouseButton.Left)
this.DragMove();
}
private void img_forward_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (ImageNumber+1 >= Classes.DataHouse.images.Count)
ImageNumber = 0;
else
ImageNumber++;
Uri myUri = new Uri(Classes.DataHouse.images[ImageNumber], UriKind.RelativeOrAbsolute);
decoder2 = new GifBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
}
private void Grid_MouseEnter(object sender, MouseEventArgs e)
{
mouseIn = true;
Thread th = new Thread(() =>
{
while (opasity < 100 && mouseIn)
{
System.Threading.Thread.Sleep(25);
opasity++;
try
{
this.Dispatcher.Invoke(new Action(delegate()
{
img_forward.Opacity = opasity / 100;
img_exit.Opacity = opasity / 100;
img_backward.Opacity = opasity / 100;
}));
}
catch
{
//the thread was probably aborted
}
}
});
threadList.Add(th);
th.Start();
}
private void Grid_MouseLeave(object sender, MouseEventArgs e)
{
mouseIn = false;
Thread th = new Thread(() =>
{
while (opasity > 0 && !mouseIn)
{
System.Threading.Thread.Sleep(25);
opasity--;
try{
this.Dispatcher.Invoke(new Action(delegate()
{
img_forward.Opacity = opasity / 100;
img_exit.Opacity = opasity / 100;
img_backward.Opacity = opasity / 100;
}));
}
catch
{
//the thread was probably aborted
}
}
});
threadList.Add(th);
th.Start();
}
private void img_backward_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (ImageNumber - 1 < 0)
ImageNumber = Classes.DataHouse.images.Count-1;
else
ImageNumber--;
Uri myUri = new Uri(Classes.DataHouse.images[ImageNumber], UriKind.RelativeOrAbsolute);
decoder2 = new GifBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
}
private void img_exit_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
foreach (Thread th in threadList)
{
while(th.ThreadState == ThreadState.Running)
th.Abort();
}
programClosed = true;
this.Close();
}
}
}
Unfortunately, animated GIF images were somewhat of an oversight when Microsoft developed WPF, so there is no 'built in' functionality that handles this. There are several working examples found online, but you should still be aware that code needs to be run on the UI thread to animate these images.
Therefore, certain situations, such as trying to use a 'busy' GIF during loading will not work because the UI thread will already be busy.
Having announced that disclaimer, you can find some working code that will do what you want in Thomas Levesque's GitHub project at the link below:
thomaslevesque/WpfAnimatedGif
Using a Thread
public MainWindow()
{
InitializeComponent();
Uri myUri = new Uri(#"Images\2b3601fe2b62e87481bd301da52a2182.gif", UriKind.RelativeOrAbsolute);
GifBitmapDecoder decoder2 = new GifBitmapDecoder(myUri, BitmapCreateOptions.PreservePixelFormat, BitmapCacheOption.Default);
BitmapSource bitmapSource2;
int frameCount = decoder2.Frames.Count;
Thread th = new Thread(() => {
while (true)
{
for (int i = 0; i < frameCount; i++)
{
this.Dispatcher.Invoke(new Action(delegate()
{
bitmapSource2 = decoder2.Frames[i];
image.Source = bitmapSource2;
}));
System.Threading.Thread.Sleep(100);
}
}
});
th.Start();
}
This only works with physical files that aren't compiled as Resources, etc.
Try to change your image resource Build Action to Content or something similar, instead of Resource (And activate Copy to Output Directory, maybe?).
I managed to get a sample working that way. The key is that you must reference a physical file in some folder or internet URL.
For more info, check this out: https://social.msdn.microsoft.com/Forums/vstudio/en-US/93d50a97-0d8d-4b18-992e-cd3200693337/how-to-use-an-animated-gif?forum=wpf
How could i update the windows audio playback agent properties like title and artist, live ,when it is playing. I want to update the title every 20 seconds without stopping the music which is playing? please help. I tried this but its stopping and replaying at every 20 seconds which is annoying. Here is the code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
using Microsoft.Phone.BackgroundAudio;
using System.Threading;
using System.Windows.Threading;
namespace PhoneApp2
{
public partial class MainPage : PhoneApplicationPage
{
DispatcherTimer timer = new DispatcherTimer();
string Artist;
string Song;
// Constructor
public MainPage()
{
InitializeComponent();
}
private void Button1_Click(object sender, RoutedEventArgs e)
{
timer.Interval = TimeSpan.FromSeconds(20);
timer.Start();
timer.Tick += timer_Tick;
}
void timer_Tick(object sender, EventArgs e)
{
WebClient client = new WebClient();
client.Encoding = System.Text.Encoding.UTF8;
client.Headers[HttpRequestHeader.IfModifiedSince] = DateTime.Now.ToString();
client.DownloadStringAsync(new Uri("http://air-online2.hitfm.md/status_hitfm.xsl"));
client.DownloadStringCompleted += client_DownloadStringCompleted;
}
void client_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
string[] FullTitle = e.Result.Substring(166).Split('-');
Artist= FullTitle[0];
if(Artist.Contains(":"))
{
Artist=FullTitle[0].Replace(":",string.Empty);
}
Song = FullTitle[1].Replace(" ", string.Empty);
if (BackgroundAudioPlayer.Instance.PlayerState != PlayState.Playing)
{
BackgroundAudioPlayer.Instance.Track = new AudioTrack(new Uri("http://air-online2.hitfm.md/hitfm.mp3"), Artist, Song, null, null);
BackgroundAudioPlayer.Instance.Play();
}
else
{
BackgroundAudioPlayer.Instance.Track = new AudioTrack(new Uri("http://air-online2.hitfm.md/hitfm.mp3"), Artist, Song, null, null);
}
}
}
}
I am new with Windows Phone animation and using the below code but it give me compile error:
'System.Windows.Controls.Button' does not contain a definition for 'BeginAnimation' and no extension method 'BeginAnimation' accepting a first argument of type 'System.Windows.Controls.Button' could be found (are you missing a using directive or an assembly reference?)
Which reference I am missing?
using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Microsoft.Phone.Controls;
private void button1_Click(object sender, RoutedEventArgs e)
{
DoubleAnimation da = new DoubleAnimation();
da.From = 30;
da.To = 100;
da.Duration = new Duration(TimeSpan.FromSeconds(1));
button1.BeginAnimation(Button.HeightProperty, da);
}
The UIElement.BeginAnimation method does not exist in WP7. Instead, you will need to create a storyboard as follows:
private void button1_Click(object sender, RoutedEventArgs e)
{
var sb = new Storyboard();
var db = CreateDoubleAnimation(30, 100,
button1, Button.HeightProperty, TimeSpan.FromMilliseconds(1000));
sb.Children.Add(db);
sb.Begin();
}
private static DoubleAnimation CreateDoubleAnimation(double from, double to,
DependencyObject target, object propertyPath, TimeSpan duration)
{
var db = new DoubleAnimation();
db.To = to;
db.From = from;
db.Duration = duration;
Storyboard.SetTarget(db, target);
Storyboard.SetTargetProperty(db, new PropertyPath(propertyPath));
return db;
}