In C# 5.0 and Window store app, the 2 most important characteristics are ( in my opinion)
XAML, MVVM pattern and asynchronous programming
In Window store app, you no longer have the window form like we have in Visual Studio 2010 or earlier. XAML is the only choice. The project template prepared you with full implementation of MVVM. Event programming in UI become the history in the past, Command and Command Binding is the way to go. The C# code is less coupled with the UI element as never before. It is so much so that all UI elements in the page do not have names. This is the evidence that the C# code we have do not access these UI elements at all.
with this design, you could have a design team solely working on UI and a development team solely working on the business logic and they can work together in the same codebase. if you are tired of doing programming , here is an opportunity for you, be a user experience designer with XAML, most likely you want to work with Blend more than Visual Studio. the market demand for XAML designer is huge. I am sure you will make some good money by just doing that. If you like I could deduct an article to XAML and Blend in my future writing. Enough talking here, let me show you some XAML code. a note here all XAML code shown here are hand-written by me, without using drag and drop in IDE or Blend, so it is not as colorful or active as it should be. but it is good enough to present you the usage of MVVM and binding concept here.
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
DataContext="{Binding Lesson}"
d:DataContext="{d:DesignData Source=/Data/SampleEditLesson.json, Type=ViewModel:EditLessonViewModel}">
<Grid.ChildrenTransitions>
<TransitionCollection>
<EntranceThemeTransition/>
</TransitionCollection>
</Grid.ChildrenTransitions>
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<!-- Back button and page title -->
<Grid Grid.Row="0" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="120"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="backButton" Margin="39,59,39,0" Command="{Binding NavigationHelper.GoBackCommand, ElementName=pageRoot}"
Style="{StaticResource NavigationBackButtonNormalStyle}"
VerticalAlignment="Top"
AutomationProperties.Name="Back"
AutomationProperties.AutomationId="BackButton"
AutomationProperties.ItemType="Navigation Button"/>
<TextBlock x:Name="pageTitle" Text="{Binding ModuleTitle}" Style="{StaticResource HeaderTextBlockStyle}" Grid.Column="1"
IsHitTestVisible="false" TextWrapping="NoWrap" VerticalAlignment="Bottom" Margin="0,0,30,40"/>
</Grid>
<Grid Grid.Row="2">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="50"/>
<RowDefinition Height="auto"/>
<RowDefinition Height="*"/>
<RowDefinition Height="70"/>
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Title" Margin="10,10,10,10" Style="{StaticResource BodyTextBlockStyle}" HorizontalAlignment="Right" VerticalAlignment="Center"/>
<TextBox x:Name="txtTitle" Grid.Row="0" Grid.Column="1" Margin="10,10,50,10" Grid.ColumnSpan="3" Height="25" Text="{Binding Title, Mode=TwoWay}"/>
<TextBlock Grid.Row="1" Grid.Column="0" Text="Description" Margin="10,10,10,0" Style="{StaticResource BodyTextBlockStyle}" HorizontalAlignment="Right" VerticalAlignment="Top"/>
<TextBox Grid.Row="1" Grid.Column="1" Margin="10,10,50,10" Grid.ColumnSpan="3" Height="100" Text="{Binding Description, Mode=TwoWay}" VerticalAlignment="Top"/>
<GridView Grid.Column="1" Grid.Row="2" Width="auto" ItemsSource="{Binding Words, Mode=TwoWay}" SelectedItem="{Binding SelectedWord, Mode=TwoWay}" CanDragItems="True" AllowDrop="True" CanReorderItems="True">
<GridView.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Spelling}" Width="100" Style="{StaticResource TitleTextBlockStyle}" Margin="10,0,10,0" HorizontalAlignment="Center"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
<StackPanel Grid.Column="2" Grid.Row="2" Orientation="Vertical" VerticalAlignment="Center">
<Button Content="Add All" Width="120" HorizontalAlignment="Center" Margin="0,10,0,10" Command="{Binding AddAllWordsCommand}"/>
<Button Content="Add" Width="120" HorizontalAlignment="Center" Margin="0,10,0, 10" Command="{Binding AddWordCommand}"/>
<Button Content="Remove" Width="120" HorizontalAlignment="Center" Margin="0,10,0, 10" Command="{Binding RemoveWordCommand}"/>
<Button Content="Remove All" Width="120" HorizontalAlignment="Center" Margin="0,10,0, 10" Command="{Binding RemoveAllWordsCommand}"/>
</StackPanel>
<GridView Grid.Column="3" Grid.Row="2" ItemsSource="{Binding AvaiableWords, Mode=TwoWay}" SelectedItem="{Binding SelectedAvaiableWord, Mode=TwoWay}" CanDragItems="True" AllowDrop="True" CanReorderItems="True">
<GridView.ItemTemplate>
<DataTemplate>
<TextBlock Width="100" Text="{Binding Spelling}" Style="{StaticResource TitleTextBlockStyle}" Margin="10,0,10,0" HorizontalAlignment="Center"/>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
<StackPanel Grid.Column="1" Grid.Row="3" Orientation="Horizontal" Grid.ColumnSpan="3" HorizontalAlignment="Center">
<Button Content="Done" Width="150" Margin="10,10,20,10" Command="{Binding SaveCommand}"/>
<Button Content="Delete" Width="150" Margin="20,10,10,10" Command="{Binding DeleteCommand}"/>
</StackPanel>
</Grid>
</Grid>
pay attention to the highlighted parts, the first highlighted potation, the code links the XAML segment with a ViewModel class by assign the an instance of the ViewModel to its data context. the following 2 lines says the following
DataContext="{Binding Lesson}"
d:DataContext="{d:DesignData Source=/Data/SampleEditLesson.json, Type=ViewModel:EditLessonViewModel}">
1) the DataContext of the Grid is set to a property of the page with the name of Lesson,
2) in design time, you will get the sample data from a Jason file and de-serialized into an object with the type of EditLessonViewModel
with those 2 lines, you will have the data in design time to see your design effect and all public members of the ViewModel is accessible with the grid. In runtime, one line in code behind will set the stage right. then you will see it dancing.
this.DefaultViewModel["Lesson"] = viewModel;
the second highlighted potation, you will see there is no event handlers in these buttons, all you see is a binding for the Command attribute. I am sure you realized that all UI elements does not have names, ( you could have them name or id if you want to do UI to UI blinding , but not to be used in C# code. I have some example for that as well)
in this pattern I could hand over a dummy ViewModel class to the UX designer ( stop calling it UI, the new term is UX ; User Experience). he or she could make the app dancing without real business logic in place. this is specifically useful when it comes to prototyping in the early stage of the project. let me stop here, If there are some interest, I could deduct an article on MVVM and how to make it work.
ok, enough said about XAML and MVVM pattern, let’s see some C# code ( or VB.Net code), after all, we are programmers, writing program code… The second characteristic in VS 2013 and C# 5.0 is asynchronous programming. if you look at any commercial product or professionally developed window program, you will find no matter how long lasting the operation is, the UI is still response to your mouse and keyboard. (MIBAM is an exception). the key for that happen is asynchronous programming . prior to Visual Studio 2012 ( there are something to say about Visual Studio 2010, if you are interested, please let me know), all we do is to create a delegate and a call back delegate and invoke the delegate, when the operation is completed, the callback delegate will be invoked. I did that in 2004 on a project when I worked as an consultant in MCS. trust me, it is very difficult to code, and much more difficult to testing. that is how we did in the past. in Visual Studio 2012, Microsoft introduced 2 new key words in language Async and await. with those 2 new magic words asynchronous programming become something “a cave man can do it”. enough talking, let me show you some code:
public async Task CreateDatabaseAsync()
{
await _connection.ExecuteAsync(SQLScripts.Create.Module);
await _connection.ExecuteAsync(SQLScripts.Create.Word);
await _connection.ExecuteAsync(SQLScripts.Create.Lesson);
await _connection.ExecuteAsync(SQLScripts.Create.LessonWord);
}
the counter part of the synchronous version would be something like
public void CreateDatabase()
{
_connection.Execute(SQLScripts.Create.Module);
_connection.Execute(SQLScripts.Create.Word);
_connection.Execute(SQLScripts.Create.Lesson);
_connection.Execute(SQLScripts.Create.LessonWord);
}
you can see there is no delegate involved, the code is very similar to what we are doing, let me explain these 2 magic words in some level of detail:
when you add await in a method call, you mean to tell .Net runtime, that, when this call is made, you want to have the control back to you and when it completed, you want to be notified with the result.
when you add async to a method, ( a sub in VB), you are telling your consumer that this method is awaitable
the naming conversion MS recommend is the name the Asyn class and members with Async suffix.
Beside this 2 magic words, there is a new library call TPL (Task Parallel Library) , with TPL, lots of things can be done in parallel to make use of multiple-core processer and multiple CPU hardware architecture. ( the server I have at home is has 2 of qual-core CPUs workstation) . if there are some interest, I could deduct some articles on Async programming or TPL.
let me show you some more complex snippets before concluding this article:
. private async Task SaveAsync(Module module, ModulePersistOptions options)
{
await _connection.RunInTransactionAsync((SQLiteConnection connection) =>
{
InsertOrReplace(module, connection);
if (module.Lessons.Count == 0)
{
if ((options & ModulePersistOptions.CreateAllWordsLesson) == ModulePersistOptions.CreateAllWordsLesson)
{
Insert(DataGenerator.PopulateLesson(module, string.Format("{0} All Words", module.Description), module.Title), connection);
}
if ((options & ModulePersistOptions.CreateDiffcultLesson) == ModulePersistOptions.CreateDiffcultLesson)
{
Insert(DataGenerator.PopulateLesson(module, string.Format("{0} Diffcult Words Only", module.Description), module.Title, 5), connection);
}
}
});
}
what I shown you here is just a tip of an iceberg, There are much more interesting topics in Window store app and Visual Studio 2013. SQLite, Microsoft Ads SDK, TTS, MS Azure Mobile service
No comments:
Post a Comment