J2i.Net

Nothing at all and Everything in general.

Changing the Background on a Button

A recent question in the Windows Phone Development Forums asking for the XAML to display a background image in a button when it is pressed. Generating the XAML to do this is pretty easy (if you know how!). While the request was for the XAML for doing this I thought the instructions for producing the XAML to do this are of great value.

Open expressions blend and start a new project. In your project add a new button. Right-click on the button and select "Edit template"->"Edit Copy" You will be prompted for the name of the new button style that we are creating (call it what you want) and whether the template will be defined in the document (page) or defined globally for the application. If you only plan on using the style in one page then it's fine to define it within the document. In general you are probably going to use your style on more than one page. In either case for this exercise select the option to create the style within the document.

Switch to code view so that we can edit the XAML. Towards the top of your document you will see a style defined with the name you gave to it. Scroll down within the style until you find the construct with a ContentControl enveloped within a Border element. It will look like the following.

<Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" 
            BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" 
            CornerRadius="0" Margin="{StaticResource PhoneTouchTargetOverhang}">								
     <ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" 
                             Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" 
                             HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 
                             Padding="{TemplateBinding Padding}" 
                            VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
</Border>

We are going to make most our changes here. We need to place an image within this border element. It is going to be behind the content and so it will have to appear before the ContentControl element. The Border element can only have one child so we will need to make a Grid the Border's direct child and then place the Image element and ContentControl element within the Grid. The Image attribute will need to have a name and it will need to have its Opacity set to zero since the image usually will not be visible. The resulting XAML will look like the following.

<Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="0" Margin="{StaticResource PhoneTouchTargetOverhang}">								
	<Grid>
		<Image x:Name="BackgroundImage" Source="/Background.png" 
                            Stretch="Fill" VerticalAlignment="Bottom" Opacity="0" />
		<ContentControl x:Name="ContentContainer" 
                                       ContentTemplate="{TemplateBinding ContentTemplate}" 
                                       Content="{TemplateBinding Content}" 
                                       Foreground="{TemplateBinding Foreground}" 
                                       HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" 
                                       Padding="{TemplateBinding Padding}" 
                                       VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
	</Grid>
</Border>

Almost done! There's only a couple of things left. We want the image to be visible when the user is pressing the button. Scroll up within the template and you'll find several VisualStateGroup elements defined. This area contains the changes and transitions that need to occur on the button when certain things happen such as the button going to a disabled state, loosing or gaining focus, and so on. We are interested in changes that occur in the pressed state. Within the VisualState named Press is a StoryBoard containing several animations. We need to add one more animation that changes the opacity of our button. As the last child of the StoryBoard element add the following.

<DoubleAnimation To="100" Duration="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundImage" />

Now if you run the project you'll see the image show up in the button any time you press it, and disappear when ever you release it. Now how do you use this in another project? If you copy the Style element from this project and place it as a resource within your other projects it will be readily available for you (just make sure that your image source also appears in your target project). The style can be applied to a button through setting the buttons style.

<Button  Style="{StaticResource MyCustomButton}"/>

If you want to see what my entire style looks like here it is.

<Style x:Key="MyCustomButton" TargetType="Button">
	<Setter Property="Background" Value="Transparent"/>
	<Setter Property="BorderBrush" Value="{StaticResource PhoneForegroundBrush}"/>
	<Setter Property="Foreground" Value="{StaticResource PhoneForegroundBrush}"/>
	<Setter Property="BorderThickness" Value="{StaticResource PhoneBorderThickness}"/>
	<Setter Property="FontFamily" Value="{StaticResource PhoneFontFamilySemiBold}"/>
	<Setter Property="FontSize" Value="{StaticResource PhoneFontSizeMediumLarge}"/>
	<Setter Property="Padding" Value="10,3,10,5"/>
	<Setter Property="Template">
		<Setter.Value>
			<ControlTemplate TargetType="Button">
				<Grid Background="Transparent">
					<VisualStateManager.VisualStateGroups>
						<VisualStateGroup x:Name="CommonStates">
							<VisualState x:Name="Normal"/>
							<VisualState x:Name="MouseOver"/>
							<VisualState x:Name="Pressed">
								<Storyboard>
									<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
										<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneBackgroundBrush}"/>
									</ObjectAnimationUsingKeyFrames>
									<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
										<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
									</ObjectAnimationUsingKeyFrames>
									<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
										<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneForegroundBrush}"/>
									</ObjectAnimationUsingKeyFrames>
									<DoubleAnimation To="100" Duration="0" Storyboard.TargetProperty="Opacity" Storyboard.TargetName="BackgroundImage" />
								</Storyboard>
							</VisualState>
							<VisualState x:Name="Disabled">
								<Storyboard>
									<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentContainer">
										<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
									</ObjectAnimationUsingKeyFrames>
									<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ButtonBackground">
										<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource PhoneDisabledBrush}"/>
									</ObjectAnimationUsingKeyFrames>
									<ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="ButtonBackground">
										<DiscreteObjectKeyFrame KeyTime="0" Value="Transparent"/>
									</ObjectAnimationUsingKeyFrames>
								</Storyboard>
							</VisualState>
						</VisualStateGroup>
					</VisualStateManager.VisualStateGroups>
					<Border x:Name="ButtonBackground" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}" CornerRadius="0" Margin="{StaticResource PhoneTouchTargetOverhang}">								
						<Grid>
							<Image x:Name="BackgroundImage" Source="/Background.png" Stretch="Fill" VerticalAlignment="Bottom" Opacity="0" />
							<ContentControl x:Name="ContentContainer" ContentTemplate="{TemplateBinding ContentTemplate}" Content="{TemplateBinding Content}" Foreground="{TemplateBinding Foreground}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
						</Grid>
					</Border>
					
				</Grid>
			</ControlTemplate>
		</Setter.Value>
	</Setter>
</Style>

iOS Firmware Expired?

This always happens to me. After installing a beta/pre release version of iOS I forget to install the final version when it comes out and the firmware expires. Unlike regular firmware updates I've never been prompted by iTunes to perform an update of the firmware when a release version is available. It seems that one has to download it and install it manually. When the firmware expires you end up with a device that has all of the notifications and reminders still showing up but the inability to get to the applications producing those notifications or reminders. 

Anyway, this happened to me again the other day. I didn't feel like addressing it then, but now that I've got the time I'm downloading the updated firmware (manually) to install. I found the site iPhoneFirmware.com which keeps track of the direct links to all of the iOS device firmware. Makes it much easier to find what I need. On the downside this looks to be a 30 minute download, so I'll go do some other development for a while. 

New Hardware: Samsung Galaxy Tab

If you follow me on Twitter you'll know I've been looking for a new tablet device. I've made my decision. I was originally going to get a Windows tablet. But when I looked at the available tablets I found that the emphasis seems to be on making them smaller and lighter and as a consequence they are lower powered than what I have with longer battery life. I get pretty good battery life already, so there wasn't a big incentive for me to get a new Windows tablet just yet. Mine is good enough.

For a breif moment I considered the iPad 2 but the new unit looks to be an incremental upgrade from the original. So I'm leaving it alone.

Next on the list was an Android tablet. That's what I got, a Samsung Galaxy Tab. It's a nifty little device in it's own right. It's small enough to fit in one hand or the back pocket of some jeans (not that I recommend carrying that way, to many pick pockets around) but large enough to make for a good eBook reader. I was also pleased with how consistent it is with other Samsung devices. I'll be talking more about it (and another mobile operating system!) in the coming weeks.

Tracking High Scores on Windows Phone

Another frequent question I come across in the user forums is related to how some one implements local high scores. The question has come up frequently enough for me to conclude that its to the benifit of the community to have an implementation available that can be used in Silverlight or XNA that is ready to be used with very little setup.

So I've made a solution for others to use. By default the component will keep track of up to 10 high scores and will take care of loading and saving itself. If you add a score the component will take care of ensuring the score is in it's proper place and removing scores that are nolonger one of the top. For persisting the score information I've made use of the DataSaver<T> code from a previous blog post. I hope others will find the solution easy to use.

To get started with using the component add a reference to my component to your project. You'll want to instantiate HighScoreList passing an optional file name that it will use to save score information. It's possible to keep track of more than one high score list as long as your instances have different file names. One might want to do this if they keep track of scores in different modes separately from each other (Ex: a score list for Difficult mode, a score list for Easy mode, and so on).

HighScoreList _highScoreList = new HighScoreList("MyScores"); 

Upon instantiation the component will take care of loading any previous high scores without you doing anything more.

To add a score create a new instance of ScoreInfo and populate its PlayerName and Score fields. (There is also a ScoreDate field that automatically gets populated with the current date and time). Then use the AddScore(ScoreInfo) method on the HighScoreList instance to add it to the score list.

ScoreInfo scoreInfo = new ScoreInfo(){PlayerName = "Jack", Score = 1048576};
_highScoreList.AddScore(scoreInfo);

And that's it, there's nothing more for you to do. When you make that call the score gets added to the high score list, scores that are no longer in the top 10 (or what ever you set the limit to be) will fall off the list, and the list will automatically be persisted back to IsolatedStorage so that it is available the next time your game runs. Easy, right?

As a test project I've created a Silverlight application that allows you to enter new scores and see the behaviour of the component.

Score Keeper Screenshot

The main bits of the source code are below. First the ScoreInfo class which is nothing more than a serializable collection of three properties

/// <summary>
/// ScoreInfo contains information on a single score
/// </summary>
[DataContract]
public class ScoreInfo : INotifyPropertyChanged 
{

                
    // PlayerName - generated from ObservableField snippet - Joel Ivory Johnson
        private string _playerName = String.Empty;

    /// <summary>
    /// The name of the player that made this score
    /// </summary>
        [DataMember]
        public string PlayerName
        {
        get { return _playerName; }
            set
            {
                if (_playerName != value)
                {
                    _playerName = value;
                    OnPropertyChanged("PlayerName");
                }
            }
        }
        //-----

                
    // Score - generated from ObservableField snippet - Joel Ivory Johnson
        private int _score = 0;

    /// <summary>
    /// The score that the player made
    /// </summary>
        [DataMember]
        public int Score
        {
        get { return _score; }
            set
            {
                if (_score != value)
                {
                    _score = value;
                    OnPropertyChanged("Score");
                }
            }
        }
        //-----

                
    // ScoreDate - generated from ObservableField snippet - Joel Ivory Johnson
        private DateTime _scoreDate = DateTime.Now;

    /// <summary>
    /// The date and time that the player made the score. If this field is not 
    /// assigned a value it will automatically be assigned with the date and time
    /// that the score isntance was created
    /// </summary>
        [DataMember]
        public DateTime ScoreDate
        {
        get { return _scoreDate; }
            set
            {
                if (_scoreDate != value)
                {
                    _scoreDate = value;
                    OnPropertyChanged("ScoreDate");
                }
            }
        }
        //-----
    protected void OnPropertyChanged(String propertyName)
    {
        if(PropertyChanged!=null)
        {
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }
    }

    #region INotifyPropertyChanged Members

    public  event PropertyChangedEventHandler PropertyChanged;

    #endregion
}

And then the HighScoreList class, which is a collection class that contains the .

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.ComponentModel;
using System.Runtime.Serialization;


namespace J2i.Net.ScoreKeeper
{
    public class HighScoreList : ObservableCollection<ScoreInfo>, INotifyPropertyChanged    
    {
        static DataSaver<HighScoreList> MyDataSaver = new DataSaver<HighScoreList>();

        public HighScoreList()
        {
            
        }

        public HighScoreList(string fileName):this()
        {
            this.ScoreFileName = fileName;
            HighScoreList temp = MyDataSaver.LoadMyData(fileName);
            if(temp!=null)
            {
                foreach(var item in temp)
                {
                    Add(item);
                }
            }
        }
                
        // MaxScoreCount - generated from ObservableField snippet - Joel Ivory Johnson
        private int _maxScoreCount = 10;
        [DataMember]
        public int MaxScoreCount
        {
        get { return _maxScoreCount; }
            set
            {
                if (_maxScoreCount != value)
                {
                    _maxScoreCount = value;
                    OnPropertyChanged("MaxScoreCount");
                }
            }
        }
        //-----


                
        // ScoreFileName - generated from ObservableField snippet - Joel Ivory Johnson
        private string _scoreFileName = "DefaultScores";
        [DataMember]
        public string ScoreFileName
        {
        get { return _scoreFileName; }
            set
            {
                if (_scoreFileName != value)
                {
                    _scoreFileName = value;
                    OnPropertyChanged("ScoreFileName");
                }
            }
        }
        //-----

                
        // AutoSave - generated from ObservableField snippet - Joel Ivory Johnson
        private bool _autoSave = true;
        [DataMember]
        public bool AutoSave
        {
        get { return _autoSave; }
            set
            {
                if (_autoSave != value)
                {
                    _autoSave = value;
                    OnPropertyChanged("AutoSave");
                }
            }
        }
        //-----

        static int ScoreComparer(ScoreInfo a, ScoreInfo b)
        {
            return b.Score - a.Score;
        }

        public void SortAndDrop()
        {
            List<ScoreInfo> temp = new List<ScoreInfo>(this.Count);
            foreach(var item in this)
            {
                temp.Add(item);
            }

            if (temp.Count > MaxScoreCount)
            {
                temp.RemoveRange(MaxScoreCount - 1, (temp.Count) - (MaxScoreCount));
            }

            temp.Sort(ScoreComparer);
            this.Clear();

            temp.ForEach((o)=>Add(o));


        }

        public void Save()
        {
            if(String.IsNullOrEmpty(ScoreFileName))
                throw new ArgumentException("A file name wasn't provided");
            MyDataSaver.SaveMyData(this, ScoreFileName);
        }

        public void AddScore(ScoreInfo score)
        {
            this.Add(score);
            SortAndDrop();
            if(AutoSave)
                Save();
        }
        
        
        
        protected void OnPropertyChanged(String propertyName)
        {
            if(PropertyChanged!=null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }

        #region INotifyPropertyChanged Members

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion
    }
}

Remember to set the Input Scope!

I was testing some code out for some one that was still in development. The code wasn't yet in complete form yet but even with that being said there was one thing that was annoying me about it. It wasn't taking advantage of InputScopes. To describe it breifly an input scope is a hint for the type of data that is to be entered into a text field. When the user gives focus to a text field the system will set the keyboard to the mode most appropriate for the type of data being entered. For numeric input scopes it will set the keyboard to numeric mode. For an e-mail input scope it will default to text and a key for the @ sign, and so on. For a full list of the input scopes you can see this page on MSDN.

Using InputScopes is easy. Within your XAML on the text boxes set the InputScope property to the name of the InputScope that specifies the type of data to be entered.

<TextBox InputScope="Number" />

<TextBox InputScope="EmailNameOrAddress" />

In addition to setting the input mode of the keyboard setting the InputScope also will let the system know whether or not to use its autocomplete dictionary. If you don't set the InputScope then it's up to the user to manually change the keyboard to the mode that is appropriate for what they are entering, and that can be down right annoying when there is a lot of text to enter!

Serializing the Unserializable

I came across a post in the Windows Phone developer forums that got me thinking for a moment. The poster had asked how to serialize a class that was not serializable. The class of interest was the StrokeCollection class. The solution for this problem has actually been around for a while but under different terms. If you pick up a design patterns book and look up Data Transfer Object (DTO) you'll see what I'm talking about. For the sake of those that don't have a design patterns book handy I'll describe the concept.

A DTO exists for the sake of storing data in an object that is suitable for crossing boundaries. More times than not when I see some one talking about a DTO it is for an object that is going from an application to a database. But it's not restricted to that scenario. For the sake of answering the question for the poster I can assume that he or she wanted to transfer the data to a file. The representation of the data in a file is also a form that is suitable for transfer over a wire.

To accomplish the task I made a few classes that have some (but not all) of the same properties as the classes I needed to serialize. I didn't need to replicate all of the properties because I'm not interested in saving all of the data that the class provides. As far as functionality goes the only thing that I've put on these classes is functions for converting from the DTO to the original class and vice versa. The StrokeCollection class uses a number of other classes to represent it's data. StrokeCollection caontains instances of Stroke, which contains instances of StylusPointCollection, and that contains instances of StylusPoint. I created a similar hierarchy with the members of that hierarchy marked as serializable (with the [DataContract] attribute). For saving and loading the data I've made use of the serialization code from a previous post.

    [DataContract]
    public class StrokeDto
    {

        public StrokeDto()
        {
        }

        public StrokeDto(Stroke source)
        {
            this.StylusPointDtos = new StylusPointDtoCollection(source.StylusPoints);
        }

        public Stroke ToStroke()
        {
            Stroke retVal = new Stroke();
            if(this.StylusPointDtos!=null)
                StylusPointDtos.ForEach((o)=>retVal.StylusPoints.Add(o.ToStylusPoint()));
            return retVal;
        }

        [DataMember]
        public StylusPointDtoCollection StylusPointDtos { get; set; }
    }

    public class StrokeDtoCollection: List
    {
        public StrokeDtoCollection()
        {
        }

        public StrokeDtoCollection(StrokeCollection source):this()
        {
            foreach(Stroke s in source)
            {
                this.Add(new StrokeDto(s));
            }
        }

        public StrokeCollection ToStrokeCollection()
        {
            StrokeCollection retVal = new StrokeCollection();
            this.ForEach((o)=>retVal.Add(o.ToStroke()));
            return retVal;
        }
    }

    [DataContract]
    public class StylusPointDto
    {

        [DataMember]
        public double X { get; set;  }

        [DataMember]
        public double Y { get; set;  }

        [DataMember]
        public float PressureFactor { get; set;  }

        public StylusPointDto()
        {}

        public StylusPointDto(StylusPoint source)
        {
            this.X = source.X;
            this.Y = source.Y;
            this.PressureFactor = source.PressureFactor;
        }

        public StylusPoint ToStylusPoint()
        {
            return new StylusPoint(this.X, this.Y) {PressureFactor = this.PressureFactor};
        }
    }
    public class StylusPointDtoCollection : List
    {

        public StylusPointDtoCollection(): base()
        {}

        public StylusPointDtoCollection(StylusPointCollection source): this()
        {
            var sourceList = (from point in source select new StylusPointDto(point)).ToArray();
            this.AddRange(sourceList);
        }

        public StylusPointCollection ToStylusPointCollection()
        {
            var retVal = new StylusPointCollection();
            this.ForEach((o) => retVal.Add(o.ToStylusPoint()));
            return retVal;
        }
    }

With my class hierarchy and the serialization code I was able to load and save the stokes in a few lines of code. 

 

//Save the Strokes
var valuesaveDto = new StrokeDtoCollection(myInkPresenter.Strokes);
_myInkSaver.SaveMyData(valuesaveDto,"MyInk.ink");


//Load the Strokes
var valueDto = _myInkSaver.LoadMyData("MyInk.ink");
myInkPresenter.Strokes = valueDto.ToStrokeCollection();


Screen Shot of Drawing Program

I've put together an example program (see link at top of article) that uses the code. Word of warning, I've not implemented any tombstoning code in it. But draw what eer you like and then click on the Save button. After you exit from the program when you go back into it you'll see your picture reload.

 

Simple Data Serialization on WP7

You've got a class that contains data that you want to be able to save and load in IsolatedStorage on Windows Phone 7.  How would you go about doing that? There is more than one way, but I wanted to share a generic solution for didactic purposes; I'm finding that many begininers like to start off with a single satisficing solution and brance off into specialized solutions later.  Let's say that you are starting off with a stereotypical Employee class. 

 

class Employee 
     public int EmployeeNumber { getset; } 
     public string Name { getset; } 
     public string Department { getset; } 

 

There are a couple of problems with this employee class that make it unsuitable for the type of serialization that will be used. First the class isn't marked as public. This is a requirement for the DataContract serializaer. Secondly the class needs to be marked as serializable and the properties to be serialized must be marked. We mark the class as serializable by giving it the [DataContract] attribute. Each property that needs to be serialized must be marked with the [DataMember] attribute.  When we apply these changes the class looks like the following. 

 

[DataContract] 
public class Employee  
{  
     [DataMember] 
     public int EmployeeNumber { getset; }  
     [DataMember] 
     public string Name { getset; }  
     [DataMember] 
     public string Department { getset; }  
}  

 

There's another requirement that the class already met that I didn't mention. The class needs to have a default constructor. Sicne we've not given this class a default constructor the runtime will provide one. Now that we have a serializable class we need a way to serialize it. The DataContractSerializer would be used to handle both serialization and deserialization of the class. In it's simplest form you only need to provide the type that the serializer will handle. So a serializaer could be created with the following code. 

 

DataContractSerializer mySerializer = new DataContractSerializer(typeof(Employee)); 

 

That serializer can be used to read or write your object to a stream such as a file stream, network stream, or memory stream. I've set forth to only save and read contents from a file stream. So I've made a generic class that contains most of the logic to do that. 

 

using System; 
using System.IO; 
using System.IO.IsolatedStorage; 
using System.Runtime.Serialization; 
 
 
public class DataSaver<MyDataType> 
    private const string TargetFolderName = "MyFolderName"
    private DataContractSerializer _mySerializer; 
    private IsolatedStorageFile _isoFile; 
    IsolatedStorageFile IsoFile 
    { 
        get 
        { 
            if (_isoFile == null
                _isoFile = System.IO.IsolatedStorage.IsolatedStorageFile.GetUserStoreForApplication(); 
            return _isoFile; 
        } 
    } 
 
    public DataSaver() 
    { 
        _mySerializer = new DataContractSerializer(typeof(MyDataType)); 
    } 
 
    public void SaveMyData(MyDataType sourceData, String targetFileName) 
    { 
        string TargetFileName = String.Format("{0}/{1}.dat", TargetFolderName, targetFileName); 
        if (!IsoFile.DirectoryExists(TargetFolderName)) 
            IsoFile.CreateDirectory(TargetFolderName); 
        try 
        { 
            using (var targetFile = IsoFile.CreateFile(TargetFileName)) 
            { 
                _mySerializer.WriteObject(targetFile, sourceData); 
            } 
        } 
        catch (Exception e) 
        { 
            IsoFile.DeleteFile(TargetFileName); 
        } 
 
 
    } 
 
    public MyDataType LoadMyData(string sourceName) 
    { 
        MyDataType retVal = default(MyDataType); 
        string TargetFileName = String.Format("{0}/{1}.dat", TargetFolderName, sourceName); 
        if (IsoFile.FileExists(TargetFileName)) 
            using (var sourceStream = IsoFile.OpenFile(TargetFileName, FileMode.Open)) 
            { 
                retVal = (MyDataType)_mySerializer.ReadObject(sourceStream); 
            } 
        return retVal; 
    } 
 

 

I've hard coded the folder name in which the data will be saved (feel free to save that). When using the class you only need to pass it the object to be saved and the name of the file that it will use. 

 

//declare instance 
DataSaver<Employee> myEmployeeDataSaver = new DataSaver<Employee>(); 
 
//read Usage 
var EmployeeData = myEmployeeDataSaver.LoadMyData("MyEmployeeDataFileName"); 
 
//save Usage 
myEmployeeDataSaver.SaveMyData(myEmployee,"MyEmployeeDataFileName"); 

 

That should be enough to get you started. I'm working on a much more complete explanation to be shared later. 

Double Precision Vector3

Download the code (2.90 KB)

 

I was working on an educational project using Windows Phone and XNA on the desktop (the phone will be controlling the desktop). The project involves demonstrating the laws of celestial mechanics. So the modeled entities have attributes with large values (ex: the mass of a planet in kilograms, the distance the planet is from its sun in meters, so on). In the Xna portion of the program the Vector3 class appeared to be a good fit for modeling a planet's position, velocity, acceleration, and so on. My only concern with Vector3 is the precision of the numeric type that it uses. It uses a single precision number. When I started my initial test I was seeing how small objects reacted on the earth's surface just to make sure that my gravity calculations were correct. Everything worked fine; the object would fall toward the earth with the expected acceleration. So I went straight from modeling a small object on the earth's surface to modeling the Earth's moon. That's when things broke down. The numbers coming back from the gravity calculations were all wrong. 

It turns out I was running into a precision problem. Floating point types have enough precision to hold the final results of my calculations, but not enough prevision to hold the large intermediate values during the calculations. There are three ways to solve this:

  1. Use a Vector class with a higher precision numeric type
  2. Copy values from Vector3 to doubles, perform calculations, copy results back to Vector3
  3. Perform my calculations using Astronomical Units (AU) instead of meters. 
I started with trying to copy values to double types before doing calculations first. That works, but I had concerns with the code getting messy and the overhead in coding that way. I thought about using astronomical units. But that would add an extra mental layer of complication. I think of calculations for gravity in terms of meters and trying to work in some other unit would likely lead to problems. There was no higher precision Vector3 class available. So last night I converted the Vector3 class to a double-precision version of itself that I named Vector3D.  A majority of the methods available on Vector3 are available on the Vector3D class. 
I replaced the Vector3 with the Vector3D class and everything worked as expected. 

I figure at some point some one else will run into this problem so I've posted a copy of this class (link at the top of this entry). If I need to add more functionality to this class I'll be updating the version at the above link to. 

WP7 Team Member Interviews

There were a couple of interviews with members of the Windows Phone 7 team that I thought were worth looking at. They were both short interviews. While they don't tell you definitively what is yet to come they do show that Microsoft is aware of many of the needs expressed by the community and it also explains why Microsoft has been so quiet

From the WMPoserUser interview with Brandon Watson.

WMPowerUser.com asked Brandon Watson some consumer oriented questions in a recent interview. I don't want to repost the entire interview here (you can head to their site to see that. But there were a few replies that I wanted to mention. When asked about Enterprise Scenarios Brandon mentions some of the needs of Enterprise LOB applications such as side loading or a private Marketplace and mentioned that Microsoft is working with Enterprise customers to ensure that they have what they need. He also mentions some popular request such as sockets and databases. While nothing commiting was stated it is good to see the Microosft is aware of features that developers want and need. From reading the interview it doesn't look like we will be seeing native code any time soon (and to that I am not complaining)

Interview with Loke Uei Tan and Tim Huckaby

In Loke Uei's interview he said something that explains why Microsoft has been so quiet about forthcoming information.

It's very frustrating when people talk to you and ask you when, why, how, and you can't really share it with them. Because there are so many people working in that division. Working really hard to ship a product. We just don't want to prerelease information. Some one might take it wrongly and cause a stir. We needed to have a proper cascde of information. And that's the reason we are keeping a lot of information internal for now.

Copy and Paste rolling out for Windows Phone

Microsoft promised Copy and Paste for first quarter 2011, and today they've started to make good on that promise. The update is rolling out to developer's first so that they can test their software and then it will roll out to consumers later. For developers interested in applying the update grab the Windows Phone Developer Tools January 2011 Update.

In the tools you will find updated reference assemblies and a new version of the Emulator that has copy and paste. Your existing applications do not need to be recompiled or changed to take advantage of this update. However, since this update will affect how a tectbox behaves you will want to ensure it doesn't interfere with any textbox interactions that you have designed. For example, if your textbox is inside of another control that accepts text input then the user could encounter difficulty when trying to select text in your application. If this occurs then you'll want to make an update to your application.

The copy and paste update is currently limited to being an update just to the text box. There isn't yet programmatic access to the clip board. But don't worry, that's coming later.