Array

Notepad (Reading & Writing Files)

Must Read

Admin
Admin
Just post!

The Notepad app enables fast, efficient note-taking. It boasts the following features:

  • Auto-save, which makes jotting down notes fast and easy
  • Quick previews of each note
  • The ability to customize each note’s background/foreground colors and text size
  • The ability to email your notes

Does this sound familiar? It should, because to a user this app behaves exactly like the preceding chapter’s Passwords & Secrets app, but without the master password and associated encryption. There is one important difference in its implementation, however, that makes it interesting for this chapter. Because the notes stored by Notepad are expected to be longer than the notes stored by Passwords & Secrets, each note is persisted as a separate file in isolated storage. This enables the app to load a note’s contents on-demand rather than loading everything each time the app launches/activates (which is what happens with application settings).

The Main Page

Notepad’s main page works just like the previous chapter’s main page, but without the LoginControl user control and associated logic. Listing 22.1 contains the XAML for the main page, with differences emphasized.

LISTING 22.1 MainPage.xaml—The User Interface for Notepad’s Main Page

[code]

<phone:PhoneApplicationPage
x:Class=”WindowsPhoneApp.MainPage”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
xmlns:phone=”clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone”
xmlns:shell=”clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone”
xmlns:local=”clr-namespace:WindowsPhoneApp”
FontFamily=”{StaticResource PhoneFontFamilyNormal}”
FontSize=”{StaticResource PhoneFontSizeNormal}”
Foreground=”{StaticResource PhoneForegroundBrush}”
SupportedOrientations=”PortraitOrLandscape” shell:SystemTray.IsVisible=”True”>
<phone:PhoneApplicationPage.Resources>
<local:DateConverter x:Key=”DateConverter”/>
</phone:PhoneApplicationPage.Resources>
<!– The application bar, with one button and one menu item –>
<phone:PhoneApplicationPage.ApplicationBar>
<shell:ApplicationBar>
<shell:ApplicationBarIconButton Text=”new”
IconUri=”/Shared/Images/appbar.add.png” Click=”NewButton_Click”/>
<shell:ApplicationBar.MenuItems>
<shell:ApplicationBarMenuItem Text=”about” Click=”AboutMenuItem_Click”/>
</shell:ApplicationBar.MenuItems>
</shell:ApplicationBar>
</phone:PhoneApplicationPage.ApplicationBar>
<Grid Background=”Transparent”>
<Grid.RowDefinitions>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”*”/>
</Grid.RowDefinitions>
<!– The standard header –>
<StackPanel Grid.Row=”0” Style=”{StaticResource PhoneTitlePanelStyle}”>
<TextBlock Text=”NOTEPAD” Style=”{StaticResource PhoneTextTitle0Style}”/>
</StackPanel>
<!– Show this when there are no notes –>
<TextBlock Name=”NoItemsTextBlock” Grid.Row=”1” Text=”No notes”
Visibility=”Collapsed” Margin=”22,17,0,0”
Style=”{StaticResource PhoneTextGroupHeaderStyle}”/>
<!– The list box containing notes –>
<ListBox x:Name=”ListBox” Grid.Row=”1” ItemsSource=”{Binding}”
SelectionChanged=”ListBox_SelectionChanged”>
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<!– The title, in a style matching the note –>
<Border Background=”{Binding ScreenBrush}” Margin=”24,0” Width=”800”
MinHeight=”60” local:Tilt.IsEnabled=”True”>
<TextBlock Text=”{Binding Title}” FontSize=”{Binding TextSize}”
Foreground=”{Binding TextBrush}” Margin=”12”
VerticalAlignment=”Center”/>
</Border>
<!– The modified date –>
<TextBlock Foreground=”{StaticResource PhoneSubtleBrush}”
Text=”{Binding Modified, Converter={StaticResource DateConverter}}”
Margin=”24,0,0,12”/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</phone:PhoneApplicationPage>

[/code]

The application bar now has the “new” button from the start because there is no mode in which adding new notes is forbidden.

The code-behind for the main page is shown in Listing 22.2.

LISTING 22.2 MainPage.xaml.cs—The Code-Behind for Notepad’s Main Page

[code]

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
namespace WindowsPhoneApp
{
public partial class MainPage : PhoneApplicationPage
{
public MainPage()
{
InitializeComponent();
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
// Bind the notes list as the data source for the list box
if (this.DataContext == null)
this.DataContext = Settings.NotesList.Value;
// Clear the selection so selecting the same item twice in a row will
// still raise the SelectionChanged event
Settings.CurrentNoteIndex.Value = -1;
this.ListBox.SelectedIndex = -1;
if (Settings.NotesList.Value.Count == 0)
NoItemsTextBlock.Visibility = Visibility.Visible;
else
NoItemsTextBlock.Visibility = Visibility.Collapsed;
}
void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (ListBox.SelectedIndex >= 0)
{
// Navigate to the details page for the selected item
Settings.CurrentNoteIndex.Value = ListBox.SelectedIndex;
this.NavigationService.Navigate(new Uri(“/DetailsPage.xaml”,
UriKind.Relative));
}
}
// Application bar handlers
void NewButton_Click(object sender, EventArgs e)
{
// Create a new note and add it to the top of the list
Note note = new Note();
note.Filename = Guid.NewGuid().ToString();
note.Modified = DateTimeOffset.Now;
note.ScreenColor = Settings.ScreenColor.Value;
note.TextColor = Settings.TextColor.Value;
note.TextSize = Settings.TextSize.Value;
Settings.NotesList.Value.Insert(0, note);
// “Select” the new note
Settings.CurrentNoteIndex.Value = 0;
// Navigate to the details page for the newly created note
this.NavigationService.Navigate(new Uri(“/DetailsPage.xaml”,
UriKind.Relative));
}
void AboutMenuItem_Click(object sender, EventArgs e)
{
this.NavigationService.Navigate(new Uri(
“/Shared/About/AboutPage.xaml?appName=Notepad”, UriKind.Relative));
}
}
}

[/code]

  • The list box is now filled immediately inside OnNavigatedTo by setting the page’s data context to the list of notes.
  • The Note class, shown at the end of this chapter, is slightly different from the preceding chapter in order to accommodate its file-based storage. Inside NewButton_Click, you can see that it now has a Filename property that points to the file containing its contents. The filename is never shown in this app’s user interface; internally, each note just needs to know where to fetch its content. Therefore, when a new note is created, it is given a unique filename thanks to the Guid.NewGuid method. This returns a Globally Unique Identifier (GUID) that is unique for all practical purposes.

The Details Page

The details page, just like in Passwords & Secrets, displays the entire contents of the note and enables the user to edit it, delete it, change its settings, or email its contents. The page’s XAML is identical to DetailsPage.xaml in the preceding chapter, except the application bar is not marked with IsVisible=”False” because it doesn’t need to be hidden while the LoginControl is shown. Listing 22.3 contains the code-behind for this page with differences emphasized.

LISTING 22.3 DetailsPage.xaml.cs—The Code-Behind for Passwords & Secrets’Details Page

[code]

using System;
using System.Windows;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
using Microsoft.Phone.Tasks;
namespace WindowsPhoneApp
{
public partial class DetailsPage : PhoneApplicationPage
{
bool navigatingFrom;
string initialText = “”;
public DetailsPage()
{
InitializeComponent();
this.Loaded += DetailsPage_Loaded;
}
void DetailsPage_Loaded(object sender, RoutedEventArgs e)
{
// Automatically show the keyboard for new notes.
// This also gets called when navigating away, hence the extra check
// to make sure we’re only doing this when navigating to the page
if (this.TextBox.Text.Length == 0 && !this.navigatingFrom)
this.TextBox.Focus();
}
protected override void OnNavigatedFrom(NavigationEventArgs e)
{
this.navigatingFrom = true;
base.OnNavigatedFrom(e);
if (this.initialText != this.TextBox.Text)
{
// Automatically save the new content
Note n = Settings.NotesList.Value[Settings.CurrentNoteIndex.Value];
n.SaveContent(this.TextBox.Text);
// Update the title now, so each one can be accessed
// later without reading the file’s contents
string title = this.TextBox.Text.TrimStart();
// Don’t include more than the first 100 characters, which should be long
// enough, even in landscape with a small font
if (title.Length > 100)
title = title.Substring(0, 100);
// Fold the remaining content into a single line. We can’t use
// Environment.NewLine because it’s rn, whereas newlines inserted from
// a text box are just r
n.Title = title.Replace(‘r’, ‘ ‘);
n.Modified = DateTimeOffset.Now;
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
// Show the note’s contents
Note n = Settings.NotesList.Value[Settings.CurrentNoteIndex.Value];
if (n != null)
{
this.initialText = this.TextBox.Text = n.GetContent();
this.TextBox.Background = n.ScreenBrush;
this.TextBox.Foreground = n.TextBrush;
this.TextBox.FontSize = n.TextSize;
}
}
void TextBox_GotFocus(object sender, RoutedEventArgs e)
{
this.ApplicationBar.IsVisible = false;
}
void TextBox_LostFocus(object sender, RoutedEventArgs e)
{
this.ApplicationBar.IsVisible = true;
}
// Application bar handlers:
void DeleteButton_Click(object sender, EventArgs e)
{
if (MessageBox.Show(“Are you sure you want to delete this note?”,
“Delete note?”, MessageBoxButton.OKCancel) == MessageBoxResult.OK)
{
Note n = Settings.NotesList.Value[Settings.CurrentNoteIndex.Value];
n.DeleteContent();
Settings.NotesList.Value.Remove(n);
if (this.NavigationService.CanGoBack)
this.NavigationService.GoBack();
}
}
void EmailButton_Click(object sender, EventArgs e)
{
EmailComposeTask launcher = new EmailComposeTask();
launcher.Body = this.TextBox.Text;
launcher.Subject = “Note”;
launcher.Show();
}
void SettingsButton_Click(object sender, EventArgs e)
{
this.NavigationService.Navigate(new Uri(“/SettingsPage.xaml”,
UriKind.Relative));
}
}
}

[/code]

  • In OnNavigatedFrom, the content of the text box is saved to a file via the SaveContent method shown later in this chapter. The Title property for each note is set at this point rather than dynamically when the property is accessed because it enables each title to be shown without reading each file. Otherwise, rendering the list on the main page would end up reading the contents of every file and take away the advantage of storing the notes in files!
  • The note’s contents are immediately shown inside OnNavigatedTo with the help of a GetContent method defined on Note.
  • Inside DeleteButton_Click, the note’s DeleteContent method ensures that the backing file doesn’t get left behind when a note is deleted.

The Note Class

Listing 22.4 shows the implementation of the modified Note class used by this app, with differences from the preceding chapter emphasized.

LISTING 22.4 Note.cs—The Code-Behind for Passwords & Secrets’Details Page

[code]

using System;
using System.ComponentModel;
using System.IO;
using System.IO.IsolatedStorage;
using System.Windows.Media;
namespace WindowsPhoneApp
{
public class Note : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
// A helper method used by the properties
void OnPropertyChanged(string propertyName)
{
PropertyChangedEventHandler handler = this.PropertyChanged;
if (handler != null)
handler(this, new PropertyChangedEventArgs(propertyName));
}
DateTimeOffset modified;
public DateTimeOffset Modified
{
get { return this.modified; }
set { this.modified = value; OnPropertyChanged(“Modified”); }
}
int textSize;
public int TextSize
{
get { return this.textSize; }
set { this.textSize = value; OnPropertyChanged(“TextSize”); }
}
Color screenColor;
public Color ScreenColor
{
get { return this.screenColor; }
set { this.screenColor = value;
OnPropertyChanged(“ScreenColor”); OnPropertyChanged(“ScreenBrush”); }
}
Color textColor;
public Color TextColor
{
get { return this.textColor; }
set { this.textColor = value;
OnPropertyChanged(“TextColor”); OnPropertyChanged(“TextBrush”); }
}
// Three readonly properties whose value is computed from other properties:
public Brush ScreenBrush
{
get { return new SolidColorBrush(this.ScreenColor); }
}
public Brush TextBrush
{
get { return new SolidColorBrush(this.TextColor); }
}
string title;
public string Title
{
get { return this.title; }
set { this.title = value; OnPropertyChanged(“Title”); }
}
public string Filename { get; set; }
public void SaveContent(string content)
{
using (IsolatedStorageFile userStore =
IsolatedStorageFile.GetUserStoreForApplication())
using (IsolatedStorageFileStream stream =
userStore.CreateFile(this.Filename))
using (StreamWriter writer = new StreamWriter(stream))
{
writer.Write(content);
}
}
public string GetContent()
{
using (IsolatedStorageFile userStore =
IsolatedStorageFile.GetUserStoreForApplication())
{
if (!userStore.FileExists(this.Filename))
return “”;
else
{
using (IsolatedStorageFileStream stream =
userStore.OpenFile(this.Filename, FileMode.Open))
using (StreamReader reader = new StreamReader(stream))
return reader.ReadToEnd();
}
}
}
public void DeleteContent()
{
using (IsolatedStorageFile userStore =
IsolatedStorageFile.GetUserStoreForApplication())
userStore.DeleteFile(this.Filename);
}
}
}

[/code]

  • As implied earlier, the Title property is now a normal read-write property rather than a read-only property whose value is determined dynamically.
  • To save a new file, SaveContent first calls IsolatedStorageFile. GetUserStoreForApplication. This is the first step in any code that interacts directly with the isolated storage file system. The IsolatedStoreFile instance returned contains several methods for creating, enumerating, opening, and deleting files and folders. Once CreateFile is called, SaveContent uses a StreamWriter to easily write the passed-in string to the stream.
  • GetContent and DeleteContent work similarly to SaveContent, making use of three more methods on IsolatedStorageFile: FileExists, OpenFile, and DeleteFile. To keep the UI responsive while interacting with large files, this would be a good place to use BackgroundWorker.

When managing files, it’s tempting to simply use the IsolatedStorageFile. GetFileNames method to enumerate and perhaps display the files.This approach has problems, however. For example:

  • The isolated storage APIs don’t expose any way to discover the created/modified dates of files.Therefore, sorting files by such properties rather than the default alphabetical order requires you to store extra information (stored in the Note class in this app).
  • The list includes an extra file if you use any isolated storage application settings.These get persisted in an XML file called _ _ApplicationSettings in the root of your app’s isolated storage folder. Although you could manually filter this out, there’s no guarantee that there won’t be other special files in the future.
  • As in Windows, filenames have restrictions on their characters (such as no colons or question marks). If you use filenames as user-visible and potentially editable labels, you need to make sure you don’t introduce invalid characters.

The Settings Page

The settings page, shown in Figure 22.1, enables the customization of any note’s foreground color, background color, and text size. Although these settings are only applied to the current note (stored as properties on the Note instance), the user can check a check box to automatically apply the chosen settings to any new notes created in the future. Listing 22.5 contains the XAML for this page, and Listing 22.6 contains the code-behind.

FIGURE 22.1 The settings page exposes per-note settings and enables you to apply them to all future notes.
FIGURE 22.1 The settings page exposes per-note settings and enables you to apply them to all future notes.

LISTING 22.5 SettingsPage.xaml—The User Interface for Notepad’s Settings Page

[code]

<phone:PhoneApplicationPage
x:Class=”WindowsPhoneApp.SettingsPage”
xmlns=”http://schemas.microsoft.com/winfx/2006/xaml/presentation”
xmlns:x=”http://schemas.microsoft.com/winfx/2006/xaml”
xmlns:phone=”clr-namespace:Microsoft.Phone.Controls;assembly=Microsoft.Phone”
xmlns:shell=”clr-namespace:Microsoft.Phone.Shell;assembly=Microsoft.Phone”
xmlns:local=”clr-namespace:WindowsPhoneApp”
FontFamily=”{StaticResource PhoneFontFamilyNormal}”
FontSize=”{StaticResource PhoneFontSizeNormal}”
Foreground=”{StaticResource PhoneForegroundBrush}”
SupportedOrientations=”PortraitOrLandscape” shell:SystemTray.IsVisible=”True”>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”*”/>
</Grid.RowDefinitions>
<!– The standard settings header –>
<StackPanel Grid.Row=”0” Style=”{StaticResource PhoneTitlePanelStyle}”>
<TextBlock Text=”SETTINGS” Style=”{StaticResource PhoneTextTitle0Style}”/>
<TextBlock Text=”notepad” Style=”{StaticResource PhoneTextTitle1Style}”/>
</StackPanel>
<ScrollViewer Grid.Row=”1”>
<Grid Margin=”{StaticResource PhoneMargin}”>
<Grid.RowDefinitions>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”Auto”/>
<RowDefinition Height=”Auto”/>
<RowDefinition/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<CheckBox x:Name=”MakeDefaultCheckBox” Grid.ColumnSpan=”2”
Content=”Make these the default settings” Margin=”0,-4,0,0”
Checked=”MakeDefaultCheckBox_IsCheckedChanged”
Unchecked=”MakeDefaultCheckBox_IsCheckedChanged”
local:Tilt.IsEnabled=”True”/>
<!– The two colors –>
<TextBlock Grid.Row=”1” Text=”Screen color”
Foreground=”{StaticResource PhoneSubtleBrush}” Margin=”12,8”/>
<Rectangle Grid.Row=”2” x:Name=”ScreenColorRectangle”
Margin=”{StaticResource PhoneHorizontalMargin}” Height=”90”
Stroke=”{StaticResource PhoneForegroundBrush}”
StrokeThickness=”3” local:Tilt.IsEnabled=”True”
MouseLeftButtonUp=”ScreenColorRectangle_MouseLeftButtonUp”/>
<TextBlock Grid.Row=”1” Grid.Column=”1” Text=”Text color”
Foreground=”{StaticResource PhoneSubtleBrush}” Margin=”12,8”/>
<Rectangle Grid.Row=”2” Grid.Column=”1” x:Name=”TextColorRectangle”
Height=”90” StrokeThickness=”3” local:Tilt.IsEnabled=”True”
Margin=”{StaticResource PhoneHorizontalMargin}”
Stroke=”{StaticResource PhoneForegroundBrush}”
MouseLeftButtonUp=”TextColorRectangle_MouseLeftButtonUp”/>
<!– Text size –>
<TextBlock Grid.Row=”3” Grid.ColumnSpan=”2” Text=”Text size”
Foreground=”{StaticResource PhoneSubtleBrush}”
Margin=”12,20,12,-14”/>
<Grid Grid.Row=”4” Grid.ColumnSpan=”2”>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width=”Auto”/>
</Grid.ColumnDefinitions>
<Slider x:Name=”TextSizeSlider” Minimum=”12” Maximum=”100”
ValueChanged=”TextSizeSlider_ValueChanged”/>
<Button x:Name=”ResetButton” Grid.Column=”1” Content=”reset”
VerticalAlignment=”Top” Click=”ResetButton_Click”
local:Tilt.IsEnabled=”True”/>
</Grid>
<!– Sample text –>
<Rectangle x:Name=”SampleBackground” Grid.Row=”5” Grid.ColumnSpan=”2”
Margin=”-12,0,-12,-12”/>
<TextBlock x:Name=”SampleTextBlock” Grid.Row=”5” Grid.ColumnSpan=”2”
Text=”Sample text.” Padding=”12”/>
</Grid>
</ScrollViewer>
</Grid>
</phone:PhoneApplicationPage>

[/code]

LISTING 22.6 SettingsPage.xaml.cs—The Code-Behind for Notepad’s Settings Page

[code]

using System;
using System.ComponentModel;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Navigation;
using Microsoft.Phone.Controls;
namespace WindowsPhoneApp
{
public partial class SettingsPage : PhoneApplicationPage
{
public SettingsPage()
{
InitializeComponent();
}
protected override void OnBackKeyPress(CancelEventArgs e)
{
base.OnBackKeyPress(e);
// Doing this here instead of OnNavigatedFrom, so it’s not
// applied when navigating forward to color picker pages
if (Settings.MakeDefault.Value)
{
// Apply everything as defaults, too
Note n = Settings.NotesList.Value[Settings.CurrentNoteIndex.Value];
Settings.ScreenColor.Value = n.ScreenColor;
Settings.TextColor.Value = n.TextColor;
Settings.TextSize.Value = n.TextSize;
}
}
protected override void OnNavigatedTo(NavigationEventArgs e)
{
base.OnNavigatedTo(e);
Note n = Settings.NotesList.Value[Settings.CurrentNoteIndex.Value];
// Apply any color just selected from the color picker
if (Settings.TempScreenColor.Value != null)
{
n.ScreenColor = Settings.TempScreenColor.Value.Value;
Settings.TempScreenColor.Value = null;
}
if (Settings.TempTextColor.Value != null)
{
n.TextColor = Settings.TempTextColor.Value.Value;
Settings.TempTextColor.Value = null;
}
// Respect the saved settings
this.MakeDefaultCheckBox.IsChecked = Settings.MakeDefault.Value;
this.ScreenColorRectangle.Fill = new SolidColorBrush(n.ScreenColor);
this.TextColorRectangle.Fill = new SolidColorBrush(n.TextColor);
this.SampleBackground.Fill = this.ScreenColorRectangle.Fill;
this.SampleTextBlock.Foreground = this.TextColorRectangle.Fill;
this.TextSizeSlider.Value = n.TextSize;
}
void ScreenColorRectangle_MouseLeftButtonUp(object sender,
MouseButtonEventArgs e)
{
// Get a string representation of the colors we need to pass to the color
// picker, without the leading #
string currentColorString = Settings.NotesList.Value
[Settings.CurrentNoteIndex.Value].ScreenColor.ToString().Substring(1);
string defaultColorString =
Settings.ScreenColor.Value.ToString().Substring(1);
// The color picker works with the same isolated storage value that the
// Setting works with, but we have to clear its cached value to pick up
// the value chosen in the color picker
Settings.TempScreenColor.ForceRefresh();
// Navigate to the color picker
this.NavigationService.Navigate(new Uri(
“/Shared/Color Picker/ColorPickerPage.xaml?”
+ “&currentColor=” + currentColorString
+ “&defaultColor=” + defaultColorString
+ “&settingName=TempScreenColor”, UriKind.Relative));
}
void TextColorRectangle_MouseLeftButtonUp(object sender,
MouseButtonEventArgs e)
{
// Get a string representation of the colors, without the leading #
string currentColorString = Settings.NotesList.Value
[Settings.CurrentNoteIndex.Value].TextColor.ToString().Substring(1);
string defaultColorString =
Settings.TextColor.Value.ToString().Substring(1);
// The color picker works with the same isolated storage value that the
// Setting works with, but we have to clear its cached value to pick up
// the value chosen in the color picker
Settings.TempTextColor.ForceRefresh();
// Navigate to the color picker
this.NavigationService.Navigate(new Uri(
“/Shared/Color Picker/ColorPickerPage.xaml?”
+ “showOpacity=false”
+ “&currentColor=” + currentColorString
+ “&defaultColor=” + defaultColorString
+ “&settingName=TempTextColor”, UriKind.Relative));
}
void TextSizeSlider_ValueChanged(object sender,
RoutedPropertyChangedEventArgs<double> e)
{
// Gets called during InitializeComponent
if (this.TextSizeSlider != null)
{
int textSize = (int)Math.Round(this.TextSizeSlider.Value);
Settings.NotesList.Value[Settings.CurrentNoteIndex.Value].TextSize =
textSize;
this.SampleTextBlock.FontSize = textSize;
}
}
void MakeDefaultCheckBox_IsCheckedChanged(object sender, RoutedEventArgs e)
{
Settings.MakeDefault.Value = this.MakeDefaultCheckBox.IsChecked.Value;
}
void ResetButton_Click(object sender, RoutedEventArgs e)
{
int textSize = Settings.TextSize.DefaultValue;
this.TextSizeSlider.Value = textSize;
Settings.NotesList.Value[Settings.CurrentNoteIndex.Value].TextSize =
textSize;
this.SampleTextBlock.FontSize = textSize;
}
}
}

[/code]

To work with the color picker that writes directly to a key in the isolated storage application settings, TempScreenColor and TempTextColor settings are used. These values are then applied to the current note’s properties inside OnNavigatedTo.

The Finished Product

Notepad (Reading & Writing Files)

- Advertisement -

Latest News

Elevate Your Bentley Experience: The Bespoke Elegance of Bentayga EWB by Mulliner

Bentley Motors redefines the essence of bespoke luxury with the introduction of the Bentayga EWB's groundbreaking two-tone customization option—a...
- Advertisement -

More Articles Like This

- Advertisement -