Windows Phone 7 development

Posts tagged ‘Source code’

Meaning of “this” keyword in C#

Recently, I’ve been looking for all usages of “this” in C#. I couldn’t find any good article, so I’ve “grepped” the spec.
Surprisingly, I had wrong idea of “this” that is the same as in Java.

What is “this”? It is a keyword used in many object-oriented programming languages to refer to the current object. It can be implemented as a pointer (f.e. C++) or reference (f.e. Java), but in C# it has a few different meanings.

Classes

We can use “this” in 3 different context

-call other contructors

-refer to instance fields or methods

-pass current object

public class Person
{
    private string name;
    public Person()
    {
       name = "John";
    }

    public Person(string name)
    : this() // call other constructor
    {
        // this is used to qualify the field
        // “name” is hidden by parameter
        this.name = name;
    }

    public string Name
    {
        get { return name; }
    }

    private void sayHi()
    {
        Console.WriteLine("Hi");
        Foo.SayName(this); //use this to pass current object
    }

    public void Speak()
    {
        this.sayHi(); // use this to refer to an instance method
         Console.WriteLine("Want to come up and see my etchings? ");
    }
}

class Foo
{
public static void SayName(Person person)
{
Console.WriteLine("My name is  {0}", person.Name);
}
}

 

Indexers

Define an indexer for the type to have array-like semantics.

public int this[int index]
{
    get { return array[index]; }
    set { array[index] = value; }
}

Extension methods

class Foo
{
     // with “this” modifiler we can use it like instance method of Person
     public static void SayName(this Person person)
     {
          Console.WriteLine(“My name is  {0}”, person.Name);
     }
}
 

Structures

struct MyVeryOwnInteger
{
    private int x;
    public int Gimme()
    {
    // inside struct this is treated as a variable
    // not reference to current structure
    return this.x;
    }
}
 

From the spe:

1.51.7This access

A this-access consists of the reserved word this.

this-access:
this

A this-access is permitted only in the block of an instance constructor, an instance method, or an instance accessor. It has one of the following meanings:

When this is used in a primary-expression within an instance constructor of a class, it is classified as a value. The type of the value is the instance type (§1.89.1) of the class within which the usage occurs, and the value is a reference to the object being constructed.

When this is used in a primary-expression within an instance method or instance accessor of a class, it is classified as a value. The type of the value is the instance type (§1.89.1) of the class within which the usage occurs, and the value is a reference to the object for which the method or accessor was invoked.

When this is used in a primary-expression within an instance constructor of a struct, it is classified as a variable. The type of the variable is the instance type (§1.89.1) of the struct within which the usage occurs, and the variable represents the struct being constructed. The this variable of an instance constructor of a struct behaves exactly the same as an out parameter of the struct type—in particular, this means that the variable must be definitely assigned in every execution path of the instance constructor.

When this is used in a primary-expression within an instance method or instance accessor of a struct, it is classified as a variable. The type of the variable is the instance type (§1.89.1) of the struct within which the usage occurs.

If the method or accessor is not an iterator (§1.100), the this variable represents the struct for which the method or accessor was invoked, and behaves exactly the same as a ref parameter of the struct type.

If the method or accessor is an iterator, the this variable represents a copy of the struct for which the method or accessor was invoked, and behaves exactly the same as a value parameter of the struct type.

Use of this in a primary-expression in a context other than the ones listed above is a compile-time error. In particular, it is not possible to refer to this in a static method, a static property accessor, or in a variable-initializer of a field declaration.

Yet another example that C# is not Java.

Usefull helper

The default parsing method for C# using current culture, which sucks really badly. ( I wrote about it on SO)

Here a lil helper  that I use

public static class Helper
{
public static bool TryParseDouble(this TextBox textbox, out double value)
{
if (double.TryParse(textbox.Text, NumberStyles.Any, CultureInfo.InvariantCulture, out value))
{
textbox.Foreground = Brushes.Black;
return true;
}
else
{
textbox.Foreground = Brushes.Red;
return false;
}
}

public static bool TryParseDouble(this string text, out double value)
{
return double.TryParse(text, NumberStyles.Any, CultureInfo.InvariantCulture, out value);
}
}

How to play music across pages.

Silverlight for Windows Phone 7 is based on the page  navigation system. Key point is the lifetime of pages – each page is deleted while you navigate to another. To have an object(singleton f.e.) during the whole application life it could be placed in App class (App.xaml.cs file). MediaElement is definitely an object that should be one (there must be only one music player). The best and simple solution is place the MediaElement in XAML(it needs to be a part of visual tree), I have used application resources:


<!--Application Resources-->
<Application.Resources>
   <MediaElement x:Name="mediaPlayer" Source="/Sound/horrorSong.mp3" AutoPlay="False"  />
</Application.Resources>

Then you can get it from any page:

MediaElement player = null; // get the media element from App resources
if (App.Current.Resources.Contains("mediaPlayer"))
{
   player = App.Current.Resources["mediaPlayer"] as MediaElement;
}
if (player != null)
{
   player.Play();
}

MediaElement can’t play the music while Zune is connect, it is good to prompt the user about it.

if (NetworkInterface.GetIsNetworkAvailable())
{
   if (NetworkInterface.NetworkInterfaceType == NetworkInterfaceType.Ethernet)
   {
      zuneTextBlock.Visibility = System.Windows.Visibility.Visible;
      return;
   }
}
zuneTextBlock.Visibility = System.Windows.Visibility.Collapsed;

This code does not guarantee if Zune is on (User sill can have the plugged phone) but is very likely that Zune is running(Zune starts while you connect the phone).

Making Tip Calculator for Window Phone 7

Tip calculator is the one of the most useful tool/app for mobile devices.

The so-called business logic is very simple and is not very different among various versions of Tip Calcs out there. Yet, what I would like to show is my way of Metro UX which I do belive is still a part of family.

Entry animation – first user expirience.

<Storyboard  x:Name="mainInAnimation">
  <DoubleAnimation Storyboard.TargetName="ContentPanel"
   Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)"
    Duration="0:0:1" To="-20" >
    <DoubleAnimation.EasingFunction>
      <ExponentialEase  EasingMode="EaseOut"  />
    </DoubleAnimation.EasingFunction>
  </DoubleAnimation>
 <DoubleAnimation Storyboard.TargetName="TitlePanel"
   Storyboard.TargetProperty="(UIElement.RenderTransform).(CompositeTransform.TranslateX)"
   Duration="0:0:1" To="-20" >
   <DoubleAnimation.EasingFunction>
     <ExponentialEase  EasingMode="EaseOut"  />
    </DoubleAnimation.EasingFunction>
 </DoubleAnimation>
 <DoubleAnimation Storyboard.TargetName="ContentPanel"
    Storyboard.TargetProperty="Opacity" Duration="0:0:1.5" To="1">
    <DoubleAnimation.EasingFunction>
      <QuadraticEase EasingMode="EaseOut"  />
     </DoubleAnimation.EasingFunction>
    </DoubleAnimation>
</Storyboard>

It gives a nice slide animation at start-up and opacity change. I used easing fuctions to give it more natural look.

Poping Textbox.

<Storyboard  x:Name="translateAmountAnimation" >
    <DoubleAnimation Storyboard.TargetName="translateAmount"
    Storyboard.TargetProperty="Y"
    To="-3" AutoReverse="True" Duration="0:0:0.2">
    <DoubleAnimation.EasingFunction>
       <ExponentialEase  EasingMode="EaseOut"  />
    </DoubleAnimation.EasingFunction>
    </DoubleAnimation>
</Storyboard>

When Textboxes are pressed, they  move up and down.

Styling.

I have made a few changes to the default style.

  • opacity of  TexBox is 0.7
  • different margins (careful with that and bear in mind the rule of thumb – 0.9mm)
  • aligment
  • theme aware styles (like PhoneTextLargeStyle)

That is all about XAML, now C#.

/// <summary>
/// Constructor
/// </summary>
public MainPage()
{
   InitializeComponent();
   this.LayoutUpdated += new EventHandler(MainPage_LayoutUpdated);
}

The ctor is kept light-weight for faster start of app and all the details are handled by MainPage_LayoutUpdated event handler.

private void MainPage_LayoutUpdated(object sender, EventArgs e)
{
    if (m_onNavigatedToCalled)
    {
        m_onNavigatedToCalled = false;
        Dispatcher.BeginInvoke(() =>
        {
                Random random = new Random();
                var number = random.Next(1, 3);
                string fileName = String.Format(@"Images\background{0}.jpg", number);
                backgroundBrush.ImageSource = new BitmapImage(new Uri(fileName, UriKind.Relative));
                radioButton3.IsChecked = true;
                mainInAnimation.Begin();
        });
     }
}

Since we need to prepare things when everything is loaded MainPage_LayoutUpdated is a proper event but it is called everytime when layout has been updated, hence m_onNavigatedToCalled bool is init with true value and after first call of event it is set to false.
Dispatcher.BeginInvoke is a thread-safe asynchronous method for UI changes (mainly). In lambda expresion the random background is picked and animation begins (I prefer do it in code).

Orientation.

        private void PhoneApplicationPage_OrientationChanged(object sender, OrientationChangedEventArgs e)
        {
            if ((e.Orientation & PageOrientation.Portrait) == PageOrientation.Portrait)
            {
                Grid.SetRow(bottom, 1);
                Grid.SetColumn(bottom, 0);
                sumStackPanel.Margin = new Thickness(35, 30, 0, 0);
            }
            else
            {
                Grid.SetRow(bottom, 0);
                Grid.SetColumn(bottom, 1);
                sumStackPanel.Margin = new Thickness(-5, 30, 0, 0);
            }
        }

To keep UI concise I have divided main Grid into 2 kolumns and 2 rows. After OrientationChanged event  occurs bottom grid is set to next column. For the orientation changes  the Hybrid animaion do a nice job.

That is all interesting things about code. Here you can download the soultion link OR http://tipcalc.codeplex.com/

You can download Tip Calc for free form Zune marketplace! enjoy!

And here is a demo. (animations are a bit choppy because of emulator + recording software) 😉

All feedbacks and comments are welcome.

%d bloggers like this: