WPF Project Template
Select WPF Application under the Windows node of the Visual C# root.By selecting the WPF Application, we will be provided with initial Window and Application-derived types as well as the references to each of the WPF assemblies such as PresentationCore.dll, PresentationFramework.dll,WindowsBase.dll, and Extensible Application Markup Language or XAML(pronounced "zammel") definition.
At this point, we should be able to compile and run the application.
WPF Designer
Visual Studio 2013 provides a Toolbox that has numerous WPF controls,
a visual designer that can be used to assemble our UI, and a Properties
window to set the properties of a selected control.The designer for an *.axml file is divided into two panes, by default, the upper pane for the window and the bottom pane for the XAML definition.
When we try to type into the XAML pane, we may find the IntelliSense as we expected:
Handling events within a WPF application, unlike Windows Form, is not done by clicking the lightning bolt button of the Properties window. Actually, this button does not exist in WPF application! When we want to handle events for a WPF widget, we could author all of the code manually using the expected C# syntax; however, if we type an event name in the XAML editor, we will activate the New Event Handler pop-up menu as we can see from the picture below:
If we manually enter an event name encased in quotation mark, we can specify any method we want. If we would rather simply have an IDE generate a default name which takes the form NameOfControl_NameOfEvent, we can double-click the pop-up menu item. In either case, the IDE responds by adding the correct event handler in our code:
private void Button_Click(object sender, RoutedEventArgs e) { }Since we've seen the basic toos used within Visual Studio 2013 to manipulate WPF applications, let's use this IDE to build an example code that demonstrates the process of parsing XAML at runtime.
Runtime XAML
To interact with XAML at runtime, we need ti know the XamlReader and XamlWriter types, both of which are defined within the System.Windows.Markup namespace. To show how to programmatically handle a Window object from an external *.xaml file, we will use the WPF ApplicatioN project (WPFApp) we created.<!-- MainWindow.xaml --> <Window x:Class="WPFApp.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MainWindow" Height="350" Width="525" Loaded="Window_Loaded" Closed="Window_Closed" WindowStartupLocation="CenterScreen"> <DockPanel LastChildFill="True"> <!-- This button will launch a window with defined XAML--> <Button DockPanel.Dock="Top" Name="btnViewXaml" Width="100" Height="40" Content="View Xaml" Click="btnViewXaml_Click" /> <!-- Input area for the text we type in --> <TextBox AcceptsReturn="True" Name="txtXamlData" FontSize="14" Background="Black" Foreground="Yellow" BorderBrush="Blue" VerticalScrollBarVisibility="Auto" AcceptsTab="True"> </TextBox> </DockPanel> </Window>Note that we replaced the initial <Grid> with a <DockPanel> that contains a Button and a TextBox, and the Button's event Click has been handled. Also, within the <Window> element, the Loaded and Closed events of the Window itself have been added.
If we have used the designer to handle the events, we can find the following code has been generated in the file, MainWindow.xaml.cs.
using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Windows; using System.Windows.Controls; using System.Windows.Data; using System.Windows.Documents; using System.Windows.Input; using System.Windows.Media; using System.Windows.Media.Imaging; using System.Windows.Navigation; using System.Windows.Shapes; namespace WPFApp { ///At this point, we need to import the following namespaces into our MainWindow.xaml.cs:/// Interaction logic for MainWindow.xaml /// public partial class MainWindow : Window { public MainWindow() { InitializeComponent(); } private void Window_Loaded(object sender, RoutedEventArgs e) { } private void Window_Closed(object sender, EventArgs e) { } private void btnViewXaml_Click(object sender, RoutedEventArgs e) { } } }
using System.IO; using System.Windows.Markup;
Loaded Event Implementation
The Loaded event of our main window checks if there is a YourXaml.xaml file in the folder containing the application. If it exists, we will read in the data and place it into the TextBox on the main window. If not, we will fill the TextBox with an initial default XAML description of an empty window. Note that we're using <StakPanel> to set the Window's Content property.private void Window_Loaded(object sender, RoutedEventArgs e) { // When the main window of the app loads, // place basic XAML text into the text box if(File.Exists(System.Environment.CurrentDirectory + "\\YourXaml.xaml")) { txtXamlData.Text = File.ReadAllText("YourXaml.xaml"); } else { txtXamlData.Text = "<Window xmlns= \"http://schemas.microsoft.com/winfx/2006/xaml/presentation\
"\n" +"xmlns:x=\"http://schemas.microsoft.com/winfx/2006/xaml\"" +" Height=\"350\" Width=\"525\" WindowStartupLocation=\"CenterScreen\">\n" +"<StackPanel>\n" +"</StackPanel>\n" +"</Window>"; } }Now, we can compile and run this xaml viewer application:
Button Click Event Implementation
When we click the Button, we will first save the current data in the TextBox into the YourXaml.xaml file. Then, we'll read in the persistent data use File.Open() to get a Stream-derived type. This is necessary because the XamlReader.Load() method requires a Stream-derived type to represent the XAML to be parsed.After loading the XAML description of the <Window> we want to construct, create an instance of System.Windows.Window based on the in-memory XAML, and display the Window as a modal dialog.
private void btnViewXaml_Click(object sender, RoutedEventArgs e) { // Write the data in the text block to a local *.xaml file. File.WriteAllText("YourXaml.xaml", txtXamlData.Text); // This is the window that will put XAML dynamically Window myWindow = null; // Open local *.xaml file. try { using (Stream st = File.Open("YourXaml.xaml", FileMode.Open)) { // Connect the XAML to the Window object myWindow = (Window)XamlReader.Load(st); myWindow.ShowDialog(); } } catch (Exception ex) { MessageBox.Show(ex.Message); } }In the code, we wrapped much of our logic within a try/catch block to handle the case when the YourXaml.xaml contains ill-formed markup.
Closed Event Implementation
The Closed event of our Window type will ensure that the data in the TextBox is persisted to the YourXaml.xaml file:private void Window_Closed(object sender, EventArgs e) { // Write the data in the text block to a local *.xamol file File.WriteAllText("YourXaml.xaml", txtXamlData.Text); }
Final Step - Testing
Now, it's the time for testing.Run the code and enter some XAML into the text area.
<Window xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Height="350" Width="525"
WindowStartupLocation="CenterScreen">
<StackPanel>
<Rectangle Fill = "Green" Height = "40" Width = "200" />
<Button Content = "OK" Height = "40" Width = "100" />
<Label Content = "{x:Type Label}" />
</StackPanel>
</Window>
Once we click the button, we will see a window that renders our XAML definitions:Note: There are still a lot more to learn, especially, WPF Controls, and this will be in my next tutorial.
Comments
Post a Comment