Announcement

Collapse
No announcement yet.

How to create a basic text editor for Windows 8? (Windows Runtime)

Collapse
X
  • Filter
  • Time
  • Show
Clear All
new posts

  • How to create a basic text editor for Windows 8? (Windows Runtime)

    How do I create a basic text editor for Windows 8? (Windows Runtime)

    Creating Windows 8 apps are easier than you think. In fact, you can now develop apps using HTML and JavaScript, although this tutorial focuses on developing a basic text editor using Visual Basic and XAML.

    What is Xaml?

    XAML is the XML markup (coincidentally abbreviated for Extensible Application Markup Language - abbreviation pronounced "Zamel"), and is used to design the layout and controls on your application. Your application will primarily consist of a root "Grid" control, and all other controls and other objects would be contained in the Grid control.

    There are many new controls in Windows 8 for modern-style apps that are exclusively provided through the Windows Store. A new control named RichEditBox does the same kind of job the .NET controls do (i.e. the RichTextBox control for .NET apps), and when you add this control onto your application form, some XAML code is added which is what determines everything from the visibility of the control, the size, the position on the application itself, and so forth. You can also add XAML code directly in the MainPage.xaml file (which is, obviously, the main page of your application when your application is executed).

    What about the Visual Basic code?

    As well as the XAML front-end file, there is also a .vb code-behind file (and .cs for C# Windows 8 apps, etc.) for the programming and application logic of your Windows 8 app. For example, any events that occur are handled and dealt with in these code-behind files. In the XAML, you can connect a particular control to an event handler method, and in your code-behind file, you would have a method that handles that event if it is fired while your application is used.

    What does this application do?

    This application is very basic. It has a RichEditBox, two buttons for Open and Save and can determine whether a file is already open; and if so, when the "Save" button is pressed, the active file is saved instead of a dialogue being displayed to choose a location and file name for saving a new file with the contents of the RichEditBox. However, this isn't all - when you are about to show an open or save picker dialogue, you need to make sure the user is not in "snapped" mode (i.e. the application become snapped to 1/3 of the screen on the left or right). If you don't check this and either unsnap or prevent the dialogue from trying to appear, an exception will be thrown in your application and will cause your application to crash. You can force your application to become unsnapped prior to showing the dialogue which is what is done in this application. It's easy to do, too.

    What does the application look like?

    The end result is as shown below. Do bear in mind this is a demo tutorial and the design aspects are irrelevant - I'm only writing on how to write a basic Windows 8 application, not how to design your Windows 8 applications. Although if you want guidance on how to properly design your Windows 8 applications for conformity to the standards of the new Windows 8 user experience and interface, see the wide-range of tutorials at msdn.com.



    Let's get started...

    When you've created your new project in Visual Studio, in the MainPage.xaml file, the following markup code is used to determine the controls used on the application and where they are positioned. Most of the XAML code was generated automatically as controls are added on the form from the Toolbox on the left. All controls in the XAML code below are part of the Windows.UI.Xaml.Controls class namespace that is part the Windows Runtime. For example, if you access the msdn documentation for the Button class in the Windows.UI.Xaml.Controls namespace, you'll see all the information regarding the Button control, including its constructor, events, methods and properties. When you set the text in the Button using the Content XAML attribute, you are making use of the Content property found here as part of the msdn documentation.

    And the XAML markup:

    Code:
    <Page
        x:Class="Text_Editor.MainPage"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:local="using:Text_Editor"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        mc:Ignorable="d">
    
        <Grid Background="{StaticResource AppBarBackgroundThemeBrush}">
            <Grid.RowDefinitions>
                <RowDefinition Height="14*"/>
                <RowDefinition Height="13*"/>
                <RowDefinition Height="229*"/>
            </Grid.RowDefinitions>
    
            <StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Grid.Row="0" Margin="5,5,0,0" Height="44" Grid.RowSpan="2" Width="221">
                <TextBlock TextWrapping="Wrap" FontSize="36" Height="39" Margin="0,0,-569,0" >
                	<Run Text="Simple Text "/>
                	<Run Text="Editor"/>
                </TextBlock>
            </StackPanel>
    
            <StackPanel HorizontalAlignment="Left" VerticalAlignment="Top" Orientation="Horizontal" Grid.Row="1" Margin="5,0,0,0" Height="38" Width="246">
                <Button x:Name="OpenButton" Content="Open" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="15,0,0,0"/>
                <Button x:Name="SaveButon" Content="Save..." HorizontalAlignment="Stretch" VerticalAlignment="Bottom" Margin="15,0,0,0" Height="38"/>
            </StackPanel>
            
            <RichEditBox x:Name="TextBox" Grid.Row="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
            
        </Grid>
    </Page>
    The code-behind (MainPage.xaml.vb) Visual Basic code:

    Code:
    'Copyright (c) eUKhost Ltd. All rights are reserved.
    
    'DISCLAIMER OF LIABILITY:
    
    'THIS CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
    'ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING ANY 
    'IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR 
    'PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
    
    Imports Windows.UI.Popups
    Imports Windows.Storage
    Imports Windows.Storage.Pickers
    
    Public NotInheritable Class MainPage
        Inherits Page
    
        Private ActiveTabs As Integer = 0
    
        Private ActiveFile As StorageFile
    
        Private Sub TextBox_KeyDown(sender As Object, e As KeyRoutedEventArgs) Handles TextBox.KeyDown
            If e.Key = Windows.System.VirtualKey.Tab Then
                e.Handled = True
                Dim SelectionText As String = ""
                TextBox.Document.Selection.GetText(Windows.UI.Text.TextGetOptions.None, SelectionText)
                TextBox.Document.Selection.TypeText(vbTab + SelectionText)
            End If
        End Sub
    
        Private Sub OpenButton_Click(sender As Object, e As RoutedEventArgs) Handles OpenButton.Click
            If ApplicationView.Value = ApplicationViewState.Snapped Then
                Dim Unsnap As Boolean = ApplicationView.TryUnsnap()
                If Unsnap = False Then
                    Exit Sub
                End If
            End If
            Me.ShowOpenFilePicker()
        End Sub
    
        Private Sub SaveButon_Click(sender As Object, e As RoutedEventArgs) Handles SaveButon.Click
            If ApplicationView.Value = ApplicationViewState.Snapped Then
                Dim Unsnap As Boolean = ApplicationView.TryUnsnap()
                If Unsnap = False Then
                    Exit Sub
                End If
            End If
            Me.ShowSaveFilePicker()
        End Sub
    
        Private Async Sub ShowOpenFilePicker()
            Dim FileChooser As New FileOpenPicker()
            FileChooser.FileTypeFilter.Add(".txt")
            Dim FilePicked As StorageFile = Await FileChooser.PickSingleFileAsync()
    
            If FilePicked IsNot Nothing Then
                Dim FileContents As String = Await FileIO.ReadTextAsync(FilePicked)
                TextBox.Document.SetText(Windows.UI.Text.TextSetOptions.None, FileContents)
    
                Me.ActiveFile = FilePicked
            End If
        End Sub
    
        Private Async Sub ShowSaveFilePicker()
            Dim TextBoxText As String = ""
    
            If Me.ActiveFile IsNot Nothing Then
                TextBox.Document.GetText(Windows.UI.Text.TextGetOptions.UseCrlf, TextBoxText)
                Await FileIO.WriteTextAsync(Me.ActiveFile, TextBoxText)
            Else
                Dim SavePicker As New FileSavePicker
    
                SavePicker.FileTypeChoices.Add("Text File", New List(Of String) From {".txt"})
                SavePicker.FileTypeChoices.Add("Word File", New List(Of String) From {".docx"})
    
                Dim FileSaved As StorageFile = Await SavePicker.PickSaveFileAsync()
    
                If FileSaved IsNot Nothing Then
                    TextBox.Document.GetText(Windows.UI.Text.TextGetOptions.UseCrlf, TextBoxText)
                    Await FileIO.WriteTextAsync(FileSaved, TextBoxText)
                End If
            End If
        End Sub
    End Class
    Let's explain the Visual Basic code line-by-line:
    • First and foremost, we are importing three separate namespaces - namely Windows.UI.Popups, Windows.Storage and WIndows.Storage.Pickers. The former is to be able to make use of message dialogues, and the latter to be able to display the open and save file dialogues, and to open and save files on the computer.
    • The class variable property (ActiveFile) is used to determine when a file has been opened, so when the user wants to use the Save function, we will know whether to save to an existing file or not.
    • The TextBox_KeyDown subroutine is to determine when the Tab key is pressed. If it is, we want to add a tab within the RichEditBox as if the user did it. By default, focus is moved from the RichEditBox to the next object in the application. The e.Handled line is to tell Windows 8 we have dealt with the event and any default action should not be executed. The third line within the If statement is to get the text in the RichEditBox that is currently selected (hence, Selecction.GetText()) and put it in the SelectionText variable. Then, on the last line within the If statement, add a tab character (vbTab does this) and the SelectionText afterwards.
    • The OpenButton_Click subroutine is invoked when the "Open" button is clicked. As you can see, the If statement is used to check whether the application view state is currently set to "snapped". If you recall, the reason I have this check in place is because an open file dialogue will be displayed, and it cannot be displayed while the application is snapped. It either needs to be filled (2/3) or full screen. If the Unsnap is unsuccessful, we exit the subroutine; otherwise, we execute the ShowOpenFilePicker() method.
    • The SaveButton_Click subroutine similarly checks whether the application view state is set to snapped; and if not (or if unsnapped), the ShowSaveFilePicker() method is executed.
    • The ShowOpenFilePicker() subroutine has a keyword "Async" which you may be unfamiliar with. Because a dialogue box is displayed, it needs to be executed and run asynchronously so that it doesn't cause your application to hold up until the operation completes - in this case, the dialogue being displayed and a user choosing a file to open. The "Await" keyword is used to tel Windows Runtime to "halt" execution of the merthod itself until, in this case, the user chooses a file. Everything else in the subroutine I'd assume is generally self-explanatory; allthough do bear in mind that the FileIO operation is also an asynchronous operation. At the bottom of the If statement within the subroutine you will notice the ActiveFile class property is being assigned the value of the FilePicked variable, which will contain a StorageFile object - and if the user does indeed select a file to open, that object will be a StorageFile object. It turns out when you open or save a file, the method in the FileIO class (i.e. ReadTextAsync() and WriteTextAsync()) requires its argument to be a StorageFile object.
    • The ShowSaveFileDialog() does subroutine does a very similar job to the preceding subroutine. I will point out, however, that the first line in the first If statement within this subroutine has its first argument as Windows.UI.Text.TextGetOptions.UseCrlf. What is this? Well, this is to ensure when a file is saved any carriage returns/line feeds are kept in-tact (i.e. any time a user hits the Enter key for separate paragraphs, etc.)

      The FileTypeChoices.Add() lines are the file type choices. The second argument requires a list - and we can instantiate a list and add to that list right within the Add() method itself by using the "From" keyword after creating an instance of the List class.


    Download entire Visual Studio project

    Disclaimer of Liability

    Copyright (c) eUKhost Ltd. All rights are reserved.

    THIS VISUAL STUDIO PROJECT / SCRIPT / CODE IS PROVIDED "AS IS" WITHOUT WARRANTY OF ANY KIND, WHETHER EXPRESS OR IMPLIED, INCLUDING ANY IMPLIED WARRANTIES OF FITNESS FOR A PARTICULAR PURPOSE, MERCHANTABILITY, OR NON-INFRINGEMENT.
Working...
X