Random programming things I'd want to remember
Monday, January 6, 2014
Karma, Angular.JS "Module is not available!" error
C# display integer in binary format
Convert.ToString(value, 2);
Monday, December 23, 2013
Draw a dot on HTML canvas
A helpful way to debug HTML canvas while doing a lot of translations, transformations, and so on.
context.fillRect(0, 0, 2, 2);
This line prints a tiny rectangle at the point of zero coordinates.
Tuesday, December 17, 2013
Note to self: Change Foreground in WPF using C#
myTextBox.Foreground = new SolidColorBrush(Colors.White);
Wednesday, December 11, 2013
MVVM Controls inside ListBox (ItemsControl) not firing
//YourViewModel.cs: private DelegateCommand yourCommand; public YourPageConstructor() { yourCommand = new DelegateCommand(this.YourMethod); ... } private void YourMethod(object obj) { ...//do something here } public ICommand YourCommand { get { return yourCommand; } } //yourPage.xaml.cs: public yourPage() { InitializeComponent(); this.DataContext = new YourViewModel(); } //yourPage.xaml: <ListBox x:Name="yourDataControl" ...> <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <Button Command="{Binding YourCommand}" Content="YourItems" ... /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox>
You go to test your page, but your command is not firing. When you set a breakpoint at the "public ICommand YourCommand ..." line, you see that it is not being hit when the page loads. What's happening?
The thing is, your command should be a part of the collection that the ListBox is bound to for the ListBox to see (and execute it). Your command lives in your ViewModel, while the ListBox is bound to a collection. What to do? Bind your command in the following way:
//yourPage.xaml, add an x:Name attribute to the content of the opening PhoneApplicationPage tag: <phone:PhoneApplicationPage x:Class="YourProjectName.Views.yourPage" x:Name="nameYourXAMLPageName" ...> //and then change the Button's binding: <ListBox x:Name="yourDataControl" ...> <ListBox.ItemTemplate> <DataTemplate> <StackPanel> <Button Command="{Binding ElementName=nameYourXAMLPageName, Path=DataContext.YourCommand}" Content="{Binding YourItems}" ... /> </StackPanel> </DataTemplate> </ListBox.ItemTemplate> </ListBox> ...
This way, we are not embedding the command into the collection bound to ListBox, but rather, let the ListBox know where to find the command by providing the "address" of the current page's DataContext.
As usual, leave your thoughts in comments.
Monday, December 9, 2013
Today I learned: Unit testing using Visual Studio Express for Windows Phone
Now if only they allowed access to visualstudio.com for Windows Phone projects or made VS 2013 for Windows Phone available for download.
Wednesday, November 27, 2013
Error HRESULT E_FAIL has been returned from a call to a COM component error on Windows Phone
Summary:
- In your App.xaml.cs "Application_UnhandledException" method, check out the error contained in the e argument
- Mine mentioned the error in MeasureOverride method, so more than likely something was wrong with XAML
- My error happened because I 1) misspelled converter key and 2) declared converter as a resource after the declaration for the DataTemplate that used it
Long version:
I am working on a Windows Phone app. Many developers face this: you code, everything works fine. Then you change a couple of things and boom! you get a cryptic error message. In my case, the phone app kept hitting this code without no apparent reason:private void Application_UnhandledException(object sender, ApplicationUnhandledExceptionEventArgs e) { if (System.Diagnostics.Debugger.IsAttached) { // An unhandled exception has occurred; break into the debugger System.Diagnostics.Debugger.Break(); } }
I hovered my mouse cursor over the e argument of the method, and I got the following information:
MS.Internal.WrappedException: Error HRESULT E_FAIL has been returned from a call to a COM component. ---> System.Exception: Error HRESULT E_FAIL has been returned from a call to a COM component. at MS.Internal.XcpImports.CheckHResult(UInt32 hr) at MS.Internal.XcpImports.UIElement_Measure_WithDesiredSize(UIElement element, Size availableSize) at System.Windows.UIElement.Measure_WithDesiredSize(Size availableSize) at System.Windows.Controls.VirtualizingStackPanel.MeasureChild(UIElement child, Size layoutSlotSize) at System.Windows.Controls.VirtualizingStackPanel.MeasureOverride(Size constraint) at System.Windows.FrameworkElement.MeasureOverride(IntPtr nativeTarget, Double inWidth, Double inHeight, Double& outWidth, Double& outHeight) --- End of inner exception stack trace ---}
After a closer look, I noticed that the code mentions MeasureOverride method. I immediately turned to my last XAML document that I edited. Lo and behold, one of the lines was highlighted blue. I added a Converter to one of the values, and I misspelled the Key parameter inside the element. I fixed the typo and voila! same error. Here is an important detail about my scenario: I have a page with resources. I use a converter within a DataTemplate resource declaration. I also declared my local converter resource after the DataTemplate (that uses it). My error kept occuring (now) because I use a resource before I declared it. I changed my page to the following (just an idea):
<phone:PhoneApplicationPage.Resources> <local:myConverter x:Key="... <DataTemplate x:Key="... ... </DataTemplate </phone:PhoneApplicationPage.Resources>
And everything started working.
Tuesday, November 26, 2013
IsolatedStorageSettings class
Today I found out that there is an IsolatedStorageSettings class that can simplify storing settings.
Sunday, October 20, 2013
Joining multiple tables in MS Access
SELECT a.AField, b.BField, c.CField FROM TableA AS a INNER JOIN (TableB AS b INNER JOIN TableC AS c ON b.BKey = c.BForeignKey) ON a.AKey = b.BForeignKey
And, by the way:
TableB AS b INNER JOIN TableC AS c ON b.BKey = c.BForeignKey AND b.BField2 = 'someValue' AND c.CField2 = 'someValue'
join condition is not supported in Access, you have to put the join by some value in the table condition into the WHERE clause:
TableB AS b INNER JOIN TableC AS c ON b.BKey = c.BForeignKey ... WHERE b.BField2 = 'someValue' AND c.CField2 = 'someValue'
Saturday, October 19, 2013
Implementing your own keyboard on Windows Phone using MVVM pattern
<Grid x:Name="LayoutRoot" Background="Transparent"> <Grid.RowDefinitions> <RowDefinition Height="Auto"/> <RowDefinition Height="Auto"/> </Grid.RowDefinitions> <TextBlock Text="{Binding MyText}" /> <ItemsControl ItemsSource="{Binding MyButtons}" HorizontalAlignment="Center" Padding="0" Grid.Row="1" Style="{StaticResource HorizontalStackPanel}" /> </Grid>
Quite a standard phone page, the first row contains the property we will be changing through the buttons that we create. The second row contains the ItemsControl that will display the collection of newly-created buttons.
What is non-standard about it is the style definiton for ItemsControl (HorizontalStackPanel). The reason for it is that by default, ItemsControl lays out its children in vertical fashion. But if you add the following code into App.xaml file in <Application.Resources> block, your items will be laid out horizontally:
<Style x:Key="HorizontalStackPanel" TargetType="ItemsControl"> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal" /> </ItemsPanelTemplate> </Setter.Value> </Setter> </Style>
Now let's get to the code-behind page, pretty easy too:
public MainPage() { InitializeComponent(); this.DataContext = new ButtonsViewModel(); }
And now let's get to the ButtonsViewModel. First, implementing the MyText property in accordance with MVVM:
private string _myText; public string MyText { get { return _myText; } set { if (_myText == value) return; _myText = value; this.RaisePropertyChanged("MyText"); } }
Then, implementing the plumbing for INotifyPropertyChanged interface:
//INotifyPropertyChanged implementation public event PropertyChangedEventHandler PropertyChanged; public void RaisePropertyChanged(string propertyName) { PropertyChangedEventHandler handler = this.PropertyChanged; if (handler != null) { handler(this, new PropertyChangedEventArgs(propertyName)); } }
And here we implement the MyButtons property by creating a list of Buttons and adding Buttons one-by-one:
//Buttons property public List<Button> MyButtons { get { List<Button> buttons = new List<Button>(); buttons.Add(MakeAButton("q"); buttons.Add(MakeAButton("w"); buttons.Add(MakeAButton("e"); buttons.Add(MakeAButton("r"); buttons.Add(MakeAButton("s"); return buttons; } } //Button plumbing private Button MakeAButton(string letter) { Button b = new Button { CommandParameter = letter, Content = new TextBlock { Text = letter, FontSize = 24, FontFamily = new System.Windows.Media.FontFamily("Segoe UI Mono") }, Height=80 }; b.Click += b_Click; return b; } //The magic void b_Click(object sender, System.Windows.RoutedEventArgs e) { string a = (sender as Button).CommandParameter.ToString(); SomeText += a; }
This example is not a classic MVVM implementation, it uses the Button Click event to alter the value of the MyText property. The classic implementation would be to use ICommand, but I chose not to do it here because this is a quick and easy example. Hopefully it can provide the feel for MVVM for those who are trying to understand the pattern.
A word of caution: if you need to fit a lot of buttons on the same row, you will be better off adjusting Margin property on each button.
Friday, October 11, 2013
Dealing with "Nested types are not supported" message while working on WPF styles.
<ItemsControl ItemsSource="{Binding MyProperty}" HorizontalAlignment="Center" Padding="0"> <ItemsControl.ItemsPanel> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal" /> </ItemsPanelTemplate> </ItemsControl.ItemsPanel> </ItemsControl>
All nice and pretty but my interface involves multiple rows of items. Naturally, I can use styles to help me with that! So I open up App.xaml and I start typing:
<Style x:Key="HorizontalStackPanel" TargetType="ItemsControl"> <Setter Property="Padding" Value="0" /> <Setter Property="ItemsPanel" Value=...
And this is where I got lost a bit, because the style does not accept nested definitions. Luckily, MSDN has a great example here. This is what I ended up writing:
<Style x:Key="HorizontalStackPanel" TargetType="ItemsControl"> <Setter Property="ItemsPanel"> <Setter.Value> <ItemsPanelTemplate> <StackPanel Orientation="Horizontal" VerticalAlignment="Center" HorizontalAlignment="Center" /> </ItemsPanelTemplate> </Setter.Value> </Setter> </Style>
And everything is working just fine. So this is how anyone can deal with the "Nested types are not supported" message while setting their styles in a somewhat complex way.
Wednesday, September 18, 2013
Efficient way to save lists to IsolatedStorage
for(int i=0;i<myList.Count;i++) await FileIO.AppendTextAsync(myFileName, myList[i]);
The method is of course marked as async, so when my debugger skipped over that line and nothing happened, I though something was wrong with Visual Studio. Then I set the debugger at my AppendTextAsync line and when it stopped, I realized that it was taking forever for the computer to append the items from my list, one-by-one (there were more than ten thousand items, and my computer is not the slowest one out there.
I recently read the book by Marijn Haverbeke called Eloquent JavaScript, which has a pretty heavy (well, in my mind) emphasis on functional programming. I remembered that there is a Join method that I could use to convert my list into a string, and I did it like so:
string result = string.Join(Environment.NewLine, myList.ToArray());and voila! It took a split second.
Windows Powershell: two commands to rule the all! Well, almost all...
Thursday, September 12, 2013
Entity Framework ignores some fields when pulling data
Let's say I have a class:
public class Bookshelf { public int BookshelfID {get;set;} public List<string>BookNames {get;set;} }
and it corresponds to a table named Bookshelves
CREATE TABLE [dbo].[Bookshelves] ( BookshelfID INT IDENTITY (1,1) NOT NULL , BookNames varchar(MAX)... , PRIMARY KEY CLUSTERED ([BookshelfID] ASC) );
in the database. Let's say we are using Entity Framework (4.0), like so:
public class EFDbContext : DbContext { public DbSet<Bookshelf> Bookshelves {get;set;} }
When Entity Framework generates the SELECT statement to pull all data from table Books, the resulting SQL will be the following:
SELECT BookshelfID FROM Bookshelves
totally ignoring the BookNames property. But if you alter the class definition such that the BookNames property is a string, the SQL statement will include BookNames column. I guess Entity Framework only works with basic types and does not trust me with explaining it how to treat the lists. You can use LINQ to Objects to extract whatever you need from BookNames.
The bottom line is: if Entity Framework is ignoring some columns in the table, check two things:
- Your class contains the corresponding property, and
- The datatype is one of these (MSDN article) primitive types.
Sunday, September 8, 2013
Separator array in place for string.Split function
.Split(new char[]{';'}, StringSplitOptions.RemoveEmptyEntries)
Thursday, May 9, 2013
Get the info on when user last set his/her password
Anyway, I found a simple solution:
net user USERNAME | find "last set"
And that did the trick.
Wednesday, January 2, 2013
Simple MVVM tutorial for Windows Phone explained
<!--ContentPanel - place additional content here--> <Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0"> <Grid.ColumnDefinitions> <ColumnDefinition Width="0.5*"/> <ColumnDefinition Width="0.5*"/> </Grid.ColumnDefinitions> <Button Content="{Binding OneText}" Command="{Binding OneCommand}" IsEnabled="{Binding IsButton1Enabled}" /> <Button Content="{Binding TwoText}" Command="{Binding TwoCommand}" IsEnabled="{Binding IsButton2Enabled}" Grid.Column="1" /> </Grid>
There are many ways to hook up ViewModel to the View. This is the simplest one:
public MainPage() { InitializeComponent(); this.DataContext = new OneViewModel(); }
The idea behind the app is very simple: there are two buttons, pressing one of them deactivates it and activates the other. It also changes the Content property of the other button. So my ViewModel should expose two properties for buttons' contents, two commands, and two properties for buttons' enabled/disabled status. Let's get to it. By the way, Random class will be my model, it will provide Content for buttons.
//ViewModel public class OneViewModel : INotifyPropertyChanged { public event PropertyChangedEventHandler PropertyChanged; Random r; private string _oneText; public string OneText { get { return this._oneText; } set { if (value == this._oneText) return; this._oneText = value; this.OnPropertyChanged("OneText"); } } private string _twoText; public string TwoText { get { return this._twoText; } set { if (value == this._twoText) return; this._twoText = value; this.OnPropertyChanged("TwoText"); } } private bool _isButton1Enabled; public bool IsButton1Enabled { get { return _isButton1Enabled; } set { if (_isButton1Enabled == value) return; _isButton1Enabled = value; this.OnPropertyChanged("IsButton1Enabled"); } } private bool _isButton2Enabled; public bool IsButton2Enabled { get { return _isButton2Enabled; } set { if (_isButton2Enabled == value) return; _isButton2Enabled = value; this.OnPropertyChanged("IsButton2Enabled"); } } private DelegateCommand _oneCommand; private DelegateCommand _twoCommand; //Constructor public OneViewModel() { r = new Random(); //This is my model IsButton1Enabled = true; IsButton2Enabled = false; OneText = r.Next(100).ToString(); TwoText = r.Next(100).ToString(); _oneCommand = new DelegateCommand(this.OneCommandAction); _twoCommand = new DelegateCommand(this.TwoCommandAction); } private void TwoCommandAction(object obj) { OneText = r.Next(100).ToString(); IsButton1Enabled = true; IsButton2Enabled = false; } private void OneCommandAction(object obj) { TwoText = r.Next(100).ToString(); IsButton1Enabled = false; IsButton2Enabled = true; } public ICommand OneCommand { get { return _oneCommand; } } public ICommand TwoCommand { get { return _twoCommand; } } private void OnPropertyChanged(string propertyName) { if (this.PropertyChanged != null) this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); } }
Not much to explain here, everything seems pretty obvious and simple. As I said before, the this.OnPropertyChanged(...) methods letting the View know that things change and the View adjusts accordingly.
Here is the definition for the DelegateCommand class.
public class DelegateCommand : ICommand { Func<object, bool> canExecute; Action<object> executeAction; public DelegateCommand(Action<object> executeAction) : this(executeAction, null) { } public DelegateCommand(Action<object> executeAction, Func<object, bool> canExecute) { if (executeAction == null) { throw new ArgumentNullException("executeAction"); } this.executeAction = executeAction; this.canExecute = canExecute; } public bool CanExecute(object parameter) //can command execute in its current status? { bool result = true; Func<object, bool> canExecuteHandler = this.canExecute; if (canExecuteHandler != null) { result = canExecuteHandler(parameter); } return result; } public event EventHandler CanExecuteChanged; //occurs when changes occur that affect whether or not the command should execute public void RaiseCanExecuteChanged() { EventHandler handler = this.CanExecuteChanged; if (handler != null) { handler(this, new EventArgs()); } } public void Execute(object parameter) //Method to call when the command is invoked { this.executeAction(parameter); } }
A couple of points of interest. If your buttons don't seem like they are reacting to the commands and you think everything is hooked up properly, check to make sure your ViewModel class is declared as public.
This site has videos on MVVM implementation for more serious things like, navigation and so on.
Also, be sure to check out my other article on MVVM where I implement a simple keyboard on Windows Phone. That tutorial is easier than this one.
For another tutorial, be sure to check my other article on the subject.
Monday, December 3, 2012
Today I learned (December 3, 2012)
Today I learned how to access StaticResource resources from xaml.cs codebehind files. This is how I'd return the regular PhoneForegroundBrush color from an IValueConverter:
return App.Current.Resources["PhoneForegroundBrush"] as SolidColorBrush;
And this is how I would emphasize text with the phone accent color.
return App.Current.Resources["PhoneForegroundBrush"] as SolidColorBrush;
Sources: source 1, source 2
Monday, October 15, 2012
Responsive UI while uploading stuff in the background Part 3
In this final post, I will make sure that the form can do work on the background, that it can inform the user about the progress, and that the user can cancel the job at any time. I will build on the code that I posted in parts 1 and 2. At part 2, I left the form fully responsive while it was doing work, but without an ability for the user to cancel work. In order to be able to cancel, I will add a Cancel property to my Uploader class like so:
public bool Cancel { get; set; }
Then, I will modify my UploadFiles method to check whether the work has been cancelled and quit the upload if needed.
public void UploadFiles() { int partTracker = 0; if (OnStartingUpload != null) //Here I need number of pieces that will be uploaded OnStartingUpload(this, new UploaderEventArgs { DataToUpload_Length = this.DataToUpload_Length, NumberOfFilesToUpload = FileNames.Count, PartsToUpload_TotalCount = this.DataToUpload_Length, PartsToUpload_UploadedSoFar = 0 }); for (int i = 0; i < FileNames.Count; i++) { if (Cancel) break; //Log.UploadingFile(FileNames[i]); if (OnStartingFileUpload != null) //here I need the number of pieces in the file that will be uploaded, and file name //OnStartingFileUpload(this, new UploaderEventArgs {NumberOfFilesToUpload=FileNames.Count, FileName = FileNames[i], FileUpload = true, FilePartUpload = false, PartsToUpload = 0, PartsUploaded = 0 }); OnStartingFileUpload(this, new FileUploaderEventArgs { FileName = FileNames[i], Cancelled=this.Cancel/*, PartsInFile = FileNames[i].Length*/ }); for (int k = 0; k < FileNames[i].Length; k++) { if (Cancel) break; //Log.UploadingPartAOfB(k+1, partsPerFile); if (OnStartingFilePartUpload != null) //here I need the number of pieces in the file that were uploaded so far and total number of pieces to upload //OnStartingFilePartUpload(this, new UploaderEventArgs { NumberOfFilesToUpload = FileNames.Count, FileName = FileNames[i], FileUpload = false, FilePartUpload = true, PartsToUpload = partsPerFile, PartsUploaded = k }); OnStartingFilePartUpload(this, new FilePartUploaderEventArgs { PartsUploadedSoFar = k, PartsToUpload = FileNames[i].Length, FileName = FileNames[i], Cancelled = this.Cancel }); Thread.Sleep(new TimeSpan(partUploadDelayNs*1000)); partTracker += 1; //Log.UploadedPartAOfB(k+1, partsPerFile); if (OnFinishedFilePartUpload != null) //here I need the number of pieces in the file that were uploaded so far and total number of pieces to upload //OnFinishedFilePartUpload(this, new UploaderEventArgs { NumberOfFilesToUpload = FileNames.Count, FileName = FileNames[i], FileUpload = false, FilePartUpload = true, PartsToUpload = partsPerFile, PartsUploaded = k }); OnFinishedFilePartUpload(this, new FilePartUploaderEventArgs { PartsUploadedSoFar = k + 1, PartsToUpload = FileNames[i].Length, FileName = FileNames[i], Cancelled = this.Cancel }); } if (OnFinishedFileUpload != null) //Here I need the file name //OnFinishedFileUpload(this, new UploaderEventArgs { NumberOfFilesToUpload = FileNames.Count, FileName = FileNames[i], FileUpload = true, FilePartUpload = false, PartsToUpload = 0, PartsUploaded = 0 }); OnFinishedFileUpload(this, new FileUploaderEventArgs { FileName = FileNames[i], Cancelled = this.Cancel/*, PartsInFile = FileNames[i].Length*/ }); } if (OnFinishedUpload != null) //Here I need the number of files uploaded OnFinishedUpload(this, new UploaderEventArgs { NumberOfFilesToUpload = FileNames.Count, Cancelled = this.Cancel }); }
Since I also notify about cancellation in the raised events, I need to update the EventArgs classes:
public class FileUploaderEventArgs : EventArgs { public string FileName { get; set; } public bool Cancelled { get; set; } //public int PartsInFile { get; set; } } public class FilePartUploaderEventArgs : EventArgs { //Number of parts uploaded so far, total number of parts to upload public int PartsUploadedSoFar { get; set; } public int PartsToUpload { get; set; } public string FileName { get; set; } public bool Cancelled { get; set; } } public class UploaderEventArgs : EventArgs { public int PartsToUpload_TotalCount { get; set; } public int PartsToUpload_UploadedSoFar { get; set; } public int DataToUpload_Length { get; set; } public int DataToUpload_Uploaded { get; set; } public int NumberOfFilesToUpload { get; set; } public string FileName { get; set; } public int PartsToUpload { get; set; } public int PartsUploaded { get; set; } public bool FileUpload { get; set; } public bool FilePartUpload { get; set; } public bool Cancelled { get; set; } }
Finally, in the stop button event handler, I need to set the Cancel property of the Uploader global variable to true:
private void stopButton_Click(object sender, RoutedEventArgs e) { u.Cancel = true; if (bg1.IsBusy) bg1.CancelAsync(); overallStatusLabel.Content = "Cancelling upload"; }
And now I have a template for a work that is done on the background that can be cancelled at any time.
Thursday, October 11, 2012
Responsive UI while uploading stuff in the background Part 2
In my previous post, I showed a program that is supposed to be doing stuff on the background, even though it was not updating the UI. In this post, I will show how to make it so that we can see the changes in the UI while the program is doing its magic.
Most of the program stayed the same, the only difference is in the MainWindow.xaml.cs. The secret weapon here is System.ComponentModel.BackgroundWorker. To successfully launch a background worker, put the time-consuming operation into the code for the worker's DoWork event. I need the interface updates here, and since my Uploader class is doing time-consuming work on another thread, I wrapped up the calls for the UI update into the Dispatcher.BeginInvoke(... code blocks. The only thing that is not working here is the event for the Stop button. It calls the background worker's CancelAsync() method, but the Uploader class cannot interrupt its actions. I will show a way to fix that in the next post.
public partial class MainWindow : Window { Stopwatch s = new Stopwatch(); Uploader u = new Uploader(); BackgroundWorker bg1 = new BackgroundWorker(); public MainWindow() { InitializeComponent(); InitializeUploaderEvents(); InitializeBackgroundWorker(); } public void InitializeUploaderEvents() { u.OnStartingUpload += new StartingUpload(u_OnStartingUpload); u.OnFinishedUpload += new FinishedUpload(u_OnFinishedUpload); u.OnStartingFileUpload += new StartingFileUpload(u_OnStartingFileUpload); u.OnFinishedFileUpload += new FinishedFileUpload(u_OnFinishedFileUpload); u.OnStartingFilePartUpload += new StartingFilePartUpload(u_OnStartingFilePartUpload); u.OnFinishedFilePartUpload += new FinishedFilePartUpload(u_OnFinishedFilePartUpload); } private void InitializeBackgroundWorker() { bg1.DoWork += new DoWorkEventHandler(bg1_DoWork); bg1.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bg1_RunWorkerCompleted); bg1.WorkerReportsProgress = true; bg1.WorkerSupportsCancellation = true; } void bg1_RunWorkerCompleted(object sender, RunWorkerCompletedEventArgs e) { if (e.Error != null) MessageBox.Show(e.Error.Message); else if (e.Cancelled) overallStatusLabel.Content = "Upload cancelled"; else { overallStatusLabel.Content = String.Format("Upload finished successfully, took {0} ", s.Elapsed); } } void bg1_DoWork(object sender, DoWorkEventArgs e) { BackgroundWorker b = sender as BackgroundWorker; Uploader u1 = e.Argument as Uploader; //I am not using this variable yet u.UploadFiles(); } void u_OnStartingFilePartUpload(object source, FilePartUploaderEventArgs e) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate() { currentFileStatusLabel.Content = String.Format("Uploading file {0}, {1}/{2} parts done.", e.FileName, e.PartsUploadedSoFar, e.PartsToUpload); fileUploadProgressBar.Maximum = e.PartsToUpload; fileUploadProgressBar.Value = e.PartsUploadedSoFar; }); } void u_OnFinishedFilePartUpload(object source, FilePartUploaderEventArgs e) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate() { currentFileStatusLabel.Content = String.Format("Uploading file {0}, {1}/{2} parts done.", e.FileName, e.PartsUploadedSoFar, e.PartsToUpload); progressBar1.Value += 1; fileUploadProgressBar.Maximum = e.PartsToUpload; fileUploadProgressBar.Value = e.PartsUploadedSoFar; }); } void u_OnStartingFileUpload(object source, FileUploaderEventArgs e) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate() { currentFileStatusLabel.Content = String.Format("Starting to upload file {0}", e.FileName); }); } void u_OnFinishedFileUpload(object source, FileUploaderEventArgs e) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate() { currentFileStatusLabel.Content = String.Format("Finished uploading file {0}", e.FileName); }); } private void startButton_Click(object sender, RoutedEventArgs e) { progressBar1.Maximum = u.DataToUpload_Length; progressBar1.Value = 0; bg1.RunWorkerAsync(); } void u_OnFinishedUpload(object source, UploaderEventArgs e) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate() { s.Stop(); overallStatusLabel.Content = String.Format("Finished uploading {0} files, elapsed time: {1}", e.NumberOfFilesToUpload, s.Elapsed); }); } void u_OnStartingUpload(object source, UploaderEventArgs e) { Dispatcher.BeginInvoke(DispatcherPriority.Normal, (ThreadStart)delegate() { overallStatusLabel.Content = String.Format("Started uploading {0} files", e.NumberOfFilesToUpload); progressBar1.Maximum = e.PartsToUpload_TotalCount; progressBar1.Value = e.PartsToUpload_UploadedSoFar; //0 s.Start(); }); } private void stopButton_Click(object sender, RoutedEventArgs e) { if (bg1.IsBusy) bg1.CancelAsync(); overallStatusLabel.Content = "Cancelling upload"; } }