Random programming things I'd want to remember

Sunday, October 20, 2013

Joining multiple tables in MS Access

The syntax is tricky and I do it every once in a while and look it up every time (because the SQL errors in MS Access are far from being user-friendly). This site here has the general idea. But the details are below:

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

In my previous article on MVVM pattern in Windows phone, I explained the entire model. Today, I will explain the usage of same pattern on Windows Phone in simpler terms. I will show how to implement a bunch of buttons (which can be repurposed for keyboard) on Windows Phone using MVVM. Let's start with a view:

    <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.

I am working on implementing an interface with many buttons on Windows Phone. First thing I learned (the hard way) is that the StackPanel does not support adding controls to it dynamically. Oh well, ItemsControl to the rescue. The tricky part about the ItemsControl is that it lays out its children vertically by default. I did some customizations to help that:

<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

I am working on a Windows 8 project and I needed a long list of strings in the isolated storage. I used this code:
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...

I borrowed a book on Powershell from Amazon, it was short and easy to read, but I only remember two commands from the book: Get-Command and Get-Help. Get-Command lists all available commands and Get-Help can tell everything about that command. If I know that I need to get something, but not sure about the command itself, I can type the following into my PowerShell window: "Get-Command -Verb Get". And if I forget how to use Get-Command, I can always type "Get-Help Get-Command". So I only need to remember one command, Get-Help!

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:
  1. Your class contains the corresponding property, and
  2. The datatype is one of these (MSDN article) primitive types.

Sunday, September 8, 2013

Separator array in place for string.Split function

Here is how to use the .Split function without having to define an array of separator values separately.

.Split(new char[]{';'}, StringSplitOptions.RemoveEmptyEntries)

Thursday, May 9, 2013

Get the info on when user last set his/her password

I needed to find out when user changed password last time and I though I would use PowerShell. There are plenty of examples in Google, but most of them refer to cases when user accounts are controlled by Active Directory. I found some script, and modified it to the extent that I was getting the number of seconds since the last time the password was changed. I learned a lot about PowerShell, too, it is great to have a .Net environment for quick tasks like that without having to compile anything.

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

Once I started learning MVVM pattern for Windows Phone, I decided to write a short sample demonstrating all the features so that I can sum it up for myself. Here it is. This article was a great starting point to understand MVVM. The most important thought I got out of that article was the INotifyProperty changed interface, which allows the controls on the phone be notified about the changes in the elements that they are bound to. We'll start with the view:
<!--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";
        }
    }


Monday, October 8, 2012

Responsive UI while uploading stuff in the background part 1


I was working on a program that required multiple uploads to be done in the background while updating the progress status for the user. I decided to go with WPF and C#. In this post, I will provide an outline for the program that simulates the upload without updating the interface. In the next posts I will explain how to update the UI and provide mechanisms to cancel uploads. Let's start with the interface:

<Window x:Class="BackgroundWorkerExperiment.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="Auto"/>
        </Grid.RowDefinitions>
        <Button x:Name="startButton" Content="Start" Click="startButton_Click" Margin="5" />
        <Button x:Name="stopButton" Content="Stop" Click="stopButton_Click" Grid.Row="1" Margin="5" />
        <StackPanel Orientation="Horizontal" Grid.Row="2">
            <ProgressBar x:Name="progressBar1" Margin="5" Width="150" />
            <Label x:Name="overallStatusLabel" Margin="5" />
        </StackPanel>
        <StackPanel Orientation="Horizontal" Grid.Row="3">
            <ProgressBar x:Name="fileUploadProgressBar" Margin="5" Width="150" />
            <Label x:Name="currentFileStatusLabel" Margin="5" />
        </StackPanel>
    </Grid>
</Window>

Pretty simple form. Next, the class with helper methods that would "generate" some files:

    public static class Helpers
    {
        private static List<char> CharacterVocabulary_Get()
        {
            List<char> vocabulary = new List<char>();

            for (int i = 48; i <= 57; i++)
            {
                char a = (char)(i);
                vocabulary.Add(a);
            }

            for (int i = 64; i < 90; i++)
            {
                char a = (char)(i);
                vocabulary.Add(a);
            }
            for (int i = 97; i <= 122; i++)
            {
                char a = (char)(i);
                vocabulary.Add(a);
            }

            return vocabulary;
        }

        public static List<string> GetListOfNStringsOfKLength(int stringCount, int stringLength)
        {
            List<string> result = new List<string>();

            Random r = new Random();
            List<char> characters = CharacterVocabulary_Get();            

            for (int k = 1; k <= stringCount; k++)
            {
                StringBuilder sb = new StringBuilder(k.ToString(), stringLength+1);

                for (int j = 0; j < stringLength; j++)
                {
                    sb.Append(characters[r.Next(characters.Count)]);

                }
                result.Add(sb.ToString());
            }

            return result;
        }

        public static List<string> GetListOfNStringsOfVariableLength(int stringCount, int minStringLength, int maxStringLength)
        {
            List<string> result = new List<string>();

            Random r = new Random();
            List<char> characters = CharacterVocabulary_Get();

            for (int k = 1; k <= stringCount; k++)
            {
                int strLength = r.Next(minStringLength, maxStringLength);

                StringBuilder sb = new StringBuilder(k.ToString(), strLength+1);

                for (int j = 0; j < strLength; j++)
                {
                    sb.Append(characters[r.Next(characters.Count)]);

                }
                result.Add(sb.ToString());
            }
            return result;
        }

    }

Now, the class that does the simulated upload. It may look complex, but it has a lot of events that it raises before and after each of the meaningful states. First, the class signals that it starts the uploading process. Then, it signals that it starts uploading a certain file. Then, it signals that it starts uploading a part of that file. Then, after some time, it signals that it finished uploading the part of the file. The class also lets its user know that it finished uploading a file, and it finished uploading everything.

    public delegate void StartingUpload(object source, UploaderEventArgs e);
    public delegate void FinishedUpload(object source, UploaderEventArgs e);

    public delegate void StartingFileUpload(object source, FileUploaderEventArgs e);
    public delegate void FinishedFileUpload(object source, FileUploaderEventArgs e);

    public delegate void StartingFilePartUpload(object source, FilePartUploaderEventArgs e);
    public delegate void FinishedFilePartUpload(object source, FilePartUploaderEventArgs e);

    class Uploader
    {
        public List<string> FileNames { get; set; }
        public int DataToUpload_Length
        {
            get
            {
                int ret = 0;
                if (FileNames == null)
                    return ret;
                else
                {
                    foreach (string s in FileNames)
                    {
                        ret += s.Length;
                    }
                    return ret;
                }
            }
        }

        private int partsPerFile = 5;
        private long partUploadDelayNs = 10000;

        public event StartingUpload OnStartingUpload;
        public event FinishedUpload OnFinishedUpload;

        public event StartingFileUpload OnStartingFileUpload;
        public event FinishedFileUpload OnFinishedFileUpload;

        public event StartingFilePartUpload OnStartingFilePartUpload;
        public event FinishedFilePartUpload OnFinishedFilePartUpload;

        public Uploader()
        {
            FileNames = Helpers.GetListOfNStringsOfVariableLength(5, 8, 15);
        }

        public Uploader(List<string> fileNames)
        {
            FileNames = fileNames;
        }

        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++)
            {
                //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 FileUploaderEventArgs { FileName = FileNames[i]/*, PartsInFile = FileNames[i].Length*/ });

                for (int k = 0; k < partsPerFile; k++)
                {
                    //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 FilePartUploaderEventArgs { PartsUploadedSoFar = k, PartsToUpload = FileNames[i].Length, FileName = FileNames[i] });

                    Thread.Sleep(new TimeSpan(partUploadDelayNs*100));
                    
                    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 FilePartUploaderEventArgs { PartsUploadedSoFar = k + 1, PartsToUpload = FileNames[i].Length, FileName = FileNames[i] });
                }

                if (OnFinishedFileUpload != null) //Here I need the file name
                     OnFinishedFileUpload(this, new FileUploaderEventArgs { FileName = FileNames[i]/*, PartsInFile = FileNames[i].Length*/ });
            }

            if (OnFinishedUpload != null) //Here I need the number of files uploaded
                OnFinishedUpload(this, new UploaderEventArgs { NumberOfFilesToUpload = FileNames.Count });
        }
    }

    public class FileUploaderEventArgs : EventArgs
    { 
        public string FileName { get; set; }
    }

    public class FilePartUploaderEventArgs : EventArgs
    {
        public int PartsUploadedSoFar { get; set; }
        public int PartsToUpload { get; set; }
        public string FileName { 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; }
    }

And now it is time to look at the code behind the main form. Nothing fancy here either. Wire up the Uploader class, let the user know what's happening in the events that it raises, make sure the start button initializes the simulation.

    public partial class MainWindow : Window
    {
        Stopwatch s = new Stopwatch();
        Uploader u = new Uploader();

        public MainWindow()
        {
            InitializeComponent();
            InitializeUploaderEvents();
        }

        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);
        }
        
        void u_OnStartingFilePartUpload(object source, FilePartUploaderEventArgs e)
        {
            currentFileStatusLabel.Content = String.Format("Uploading file {0}, {1}/{2} parts done.", e.FileName, e.PartsUploadedSoFar, e.PartsToUpload);
        }

        void u_OnFinishedFilePartUpload(object source, FilePartUploaderEventArgs e)
        {
            currentFileStatusLabel.Content = String.Format("Uploading file {0}, {1}/{2} parts done.", e.FileName, e.PartsUploadedSoFar, e.PartsToUpload);
        }

        void u_OnStartingFileUpload(object source, FileUploaderEventArgs e)
        {
            currentFileStatusLabel.Content = String.Format("Starting to upload file {0}", e.FileName);
        }

        void u_OnFinishedFileUpload(object source, FileUploaderEventArgs e)
        {
            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;
            u.UploadFiles();
        }

        void u_OnFinishedUpload(object source, UploaderEventArgs e)
        {
            s.Stop();
            overallStatusLabel.Content = String.Format("Finished uploading {0} files, elapsed time: {1}", e.NumberOfFilesToUpload, s.Elapsed);
        }

        void u_OnStartingUpload(object source, UploaderEventArgs e)
        {
            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)
        {

        }
    }

However, if you put this all together and hit the start button, there will be no feedback. The form will freeze and after a while it will unfreeze letting you know that the upload finished, but without letting you know what was happening during the upload process. Stay tuned on how to fix this.

Monday, July 30, 2012

Solving the size limitation of controls in Windows Phone 7


There is a limitation on a size of a control in Windows Phone 7 of 2048 pixels, and I needed to sometimes display a long list of items. Here is how I did that. First off, the XAML portion:

<ScrollViewer Tap="ScrollViewer_Tap" Name="AnswerScrollViewer" 
                          Grid.Row="1" Height="Auto">
    <StackPanel x:Name="AnswerScrollViewerStackPanel">
        <TextBlock x:Name="Answer"  
                      Width="430"
                      Text=""
                      Tag=""
                      FontSize="28" 
                      TextWrapping="Wrap" />
    </StackPanel>
</ScrollViewer>

There is a ScrollViewer that I use to scroll a long list. It has a StackPanel (because ScrollViewer can only have one control inside it, and I will use several controls to display a long list of text). Then the StackPanel has the "Answer" TextBlock control that is used when there is no need to display the long list.

And now, on to the magic. This is a part of the function that assigns the text to the text block.


//more on the MeasureSizeOfATextBlock() later
double futureAnswerTextBlockSize = MeasureSizeOfATextBlock(Answer, Answer.Tag.ToString());

//MAXCONTROLHEIGHT is a constant, close to 2048
if (futureAnswerTextBlockSize > MAXCONTROLHEIGHT)
{    //I split my string by the carriage returns
    string[] options = { "\r\n" };
    string[] arr = Answer.Tag.ToString().Split(options, StringSplitOptions.None);

//Let's create the first text block to start displaying the list
    TextBlock b = new TextBlock();
    b.Foreground = DarkThemeIsVisible() //more on this function later
        ? new SolidColorBrush(Color.FromArgb(255, 255, 255, 255))
        : new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));
    b.VerticalAlignment = System.Windows.VerticalAlignment.Top;
    b.FontSize = ANSWERTEXTFONTSIZE;
    b.TextWrapping = TextWrapping.Wrap;
    b.Width = 430;
    b.Name = "sb1"; //the name really does not matter

    int j = 0;
//This constant will help me omit the new line before the first line of text
    bool omitCRForNewLine = true;
//and let's display the text
    while (j < arr.Length)
    {
        if (!omitCRForNewLine)
            b.Text += Environment.NewLine + arr[j];
        else
            b.Text += arr[j];

        omitCRForNewLine = false;

        j += 1;
        if (b.ActualHeight > MAXCONTROLHEIGHT - 20)
        { //The height of the control is getting closer to the limit
//so let's add this control to the stack panel, and ...
            AnswerScrollViewerStackPanel.Children.Add(b);
//create a new control to continue displaying the text
            b = new TextBlock();
            b.Foreground = DarkThemeIsVisible()
                ? new SolidColorBrush(Color.FromArgb(255, 255, 255, 255))
                : new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));
            b.VerticalAlignment = System.Windows.VerticalAlignment.Top;
            b.FontSize = ANSWERTEXTFONTSIZE;
            b.TextWrapping = TextWrapping.Wrap;
            b.Width = 430;
            b.Name = "sb" + j.ToString();
//reset this variable to avoid the empty line in the beginning
            omitCRForNewLine = true; 
        }

        if (j == arr.Length - 1) //add the last text block
            AnswerScrollViewerStackPanel.Children.Add(b);

    } //hide Answer text block, I am not using it
    Answer.Visibility = System.Windows.Visibility.Collapsed;
}
else
{ //if one text block is enough, everything is simple
    Answer.Visibility = System.Windows.Visibility.Visible;
    Answer.Text = Answer.Tag.ToString();

    Answer.Foreground = DarkThemeIsVisible()
        ? new SolidColorBrush(Color.FromArgb(255, 255, 255, 255))
        : new SolidColorBrush(Color.FromArgb(255, 0, 0, 0));
    Answer.VerticalAlignment = System.Windows.VerticalAlignment.Top;

    Answer.FontSize = ANSWERTEXTFONTSIZE;
}


And here are the two helper functions. The first function takes a control as input, and a line of text. Then it creates a TextBlock, assigns some parameters and returns the ActualHeight parameter of the control.

private double MeasureSizeOfATextBlock(TextBlock t, string text)
{
    TextBlock a = new TextBlock();
    a.Width = t.Width;
    a.FontFamily = t.FontFamily;
    a.FontStyle = t.FontStyle;
    a.FontWeight = t.FontWeight;
    a.FontSize = t.FontSize;
    a.Text = text;
    a.TextWrapping = t.TextWrapping;

    return a.ActualHeight;
}



This function determines whether the user has the dark or light theme selected.

private bool DarkThemeIsVisible()
{
    Visibility v = (Visibility)Resources["PhoneDarkThemeVisibility"];
    if (v == System.Windows.Visibility.Visible)
        return true;

    return false;
}




Friday, July 20, 2012

Windows Phone 7 ItemsControl within an ItemsControl, solving slow loading issue


So it happened that I needed to show a long list within a long list. I found that the scrolling performance of a ListBox was not up to par, so I tried an ItemsControl. Here is the XAML:


<ItemsControl 
    MaxWidth="450" VirtualizingStackPanel.VirtualizationMode="Recycling"
    ItemsSource="{Binding AnswersForDisplayAsAListBySomeNumberOfElements}"
    Visibility="{Binding ThisOneHasALongAnswer, Converter={StaticResource showLongAnswer}}">
    <ItemsControl.ItemsPanel>
        <ItemsPanelTemplate>
            <VirtualizingStackPanel />
        </ItemsPanelTemplate>
    </ItemsControl.ItemsPanel>
    <<ItemsControl.Template>
        <ControlTemplate>
            <ScrollViewer x:Name="InnerScrollViewer" Padding="{TemplateBinding Padding}" MaxHeight="400">
                <ItemsPresenter />
            </ScrollViewer>
        </ControlTemplate>
    </ItemsControl.Template>
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding}" TextWrapping="Wrap" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>

Upon binding, if the ItemsList is visible, it displays a scrollable list. The problem with this approach is that once the inner list is scrolled to the bottom (or to the top), the outer ItemsList is not being scrolled. After playing with it for a bit, I figured out that if the ScrollViewer is removed from the ItemsControl.Template part of the control declaration, then the long list is displayed in its entire height and scrolling the individual item scrolls the entire outer ItemsList

Sunday, July 15, 2012

Extract data from an app in Windows Phone 7


I needed to export some text data out of one Windows Phone 7 application. I did not care for the format, so I thought e-mailing data to myself would be just fine. Here is some code. First, let's build the data:

public StringBuilder GetData()
{
  StringBuilder result = new StringBuilder();

  List<InventoryItem> a = ReadInventoryItems().OrderBy(x=>x.SerialNumber).OrderBy(x => x.Account).Where(x => x.isFound == true).ToList<InventoryItem>();

  foreach (InventoryItem i in a)
  {
    LocatedItem l = new LocatedItem { 
        Account = i.Account, 
        SerialNo = i.SerialNumber, 
        wasFound = i.isFound, 
        withNote = i.Note 
    };
    result.Append(l.ToString() + Environment.NewLine);
  }
  return result;
}



InventoryItem and LocatedItem are just two classes that I use to store data:
public class InventoryItem
{
    public string SerialNumber { get; set; }
    public string Account { get; set; }
    public string ModelDesc { get; set; }
    public string Building { get; set; }
    public string Room { get; set; }
    public string BuildingRoom { get; set; }
    public bool isFound { get; set; }
    public string Note { get; set; }
}

 public class LocatedItem
 {
     public string Account {get; set;}
     public string SerialNo { get; set; }
     public bool wasFound { get; set; }
     public string withNote { get; set; }

     public override string ToString()
     {
         return String.Format("{0} {1} {2} {3}", Account, SerialNo, wasFound == true ? "1" : "0", withNote);
     }
 }


Data is ready, how to extract it? The help comes from EmailComposeTask class that resides is the Microsoft.Phone.Tasks namespace. Here is some code:
EmailComposeTask email = new EmailComposeTask();
emailcomposer.To = @"youraddress@yourmailserver.com";
emailcomposer.Subject = "test subject";
DataLayer dl = new DataLayer();
emailcomposer.Body = dl.GetAllFoundItems().ToString();
emailcomposer.Show();


And that is it! Once deployed to the phone, choose the e-mail provider that will send the message and send the e-mail.

Wednesday, May 2, 2012

How to dynamically add a Border around TextBlock in Silverlight





TextBlock b = new TextBlock();
b.VerticalAlignment = System.Windows.VerticalAlignment.Top;
b.FontSize = 28;
b.TextWrapping = TextWrapping.Wrap;
b.Width = 430;
b.Text = "Hello World!";

Border a = new Border();
a.BorderThickness = new Thickness(2);
a.BorderBrush = new SolidColorBrush(Colors.Blue);
a.Child = b;

Monday, April 30, 2012

How to add Run control dynamically




textBlock.Inlines.Clear();
textBlock.Inlines.Add(new Run() { Text = Answer.Tag.ToString() });



Wednesday, April 11, 2012

How to display more than 1 text fragment on the same line using XAML

If using TextBlock, use Text.Inlines property. That can help do things like this:

<TextBlock TextWrapping="Wrap">
    <TextBlock.Inlines>
        <Run FontWeight="Bold" Text="And" />
        <Run Text=" then..." />
    </TextBlock.Inlines>
</TextBlock>


Which will look like:
And then...

If there is a need to use different types of controls, then one could use the Grid control like so:

<Grid x:Name="grid1>
  <Grid.ColumnDefinitions>
    <ColumnDefinition Width="300" />
    <ColumnDefinition Width="*"/>
  </Grid.ColumnDefinitions>
  
  <TextBlock x:Name="txtBlock1" Width="260" Grid.Column="0" Text="Text" />
  <TextBox x:Name="txtBox1" Text="a" Width="120" Grid.Column="1"></TextBox>
</Grid>

Monday, March 26, 2012

How to spell ti and di in katakana/Как написать "ти" и "ди" катаканой.

てぃ,ティ:
Type "texi" или "thi", no spaces, no quotes.
Печатайте "texi" или "thi", без кавычек.

でぃ,ディ:
Type "dexi" или "dhi", no spaces, no quotes.
Печатайте "dexi" или "dhi", без кавычек.