Windows Presentation Foundation

Download Report

Transcript Windows Presentation Foundation

Windows Presentation
Foundation
(WPF)
Introduction
• Separates appearance of user interface from behavior
• Appearance usually specified by XAML
• Behavior implemented in C# or VB
• Known as "managed languages"
• Linked by "data binding" & events
• XML can be created with graphical tools
• "Controls" can be combined ("composed")
• Image & text in a button
<Button>
<StackPanel Orientation="Vertical">
<Image Source="speaker.png" Stretch="Uniform"/>
<TextBlock Text="Play " />
</StackPanel>
</Button>
XAML language
• Includes language-level features to associate code files with markup
files, from the markup file side.
• Defines the language features
• x:Class Directive
• x:Subclass Directive
• x:ClassModifier Directive.
• Does NOT specify
• how the code should be produced
• how to integrate markup and code,
• It is left up to frameworks such as WPF to determine how to integrate the
code, how to use XAML in the application and programming models, and the
build actions or other support that all this requires.
Intro - 2
• Controls are therefore customizable
• Create "skins" for an interface using "styles"
• Similar to CSS
• "Code Behind"
• the code that is joined with markup-defined objects, when a XAML page is
markup-compiled
• Avoid or limit the use of inline code (inside XAML)
• Your event handlers in the Code Behind
• must be instance methods
• cannot be static methods
• must be defined by the partial class within the CLR namespace identified by
x:Class.
A button & its properties
Button code added by VS
Adding an event handler
1. Click the "lightning" icon
on the Properties tab, to get
this list of handlers
2. Double-Click the gray
square to get the code
added
Code added for my form
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBoxResult result = MessageBox.Show("button clicked");
Application.Current.Shutdown();
// terminates the program
}
private void CheckBox_Checked(object sender, RoutedEventArgs e)
{
// here you can add code to save the setting of the checkbox
}
• object sender – which control caused the interrupt
• RoutedEventArgs e – what the control did
• DialogResult result = Form1().ShowDialog(); is any content from the control
XAML & WPF
• XAML element corresponds to a WPF class
• Element's attributes have corresponding property/event in the class.
• Example,
<Button Background="Red"> No </Button>
• Or use C#:
Button btn = new Button();
btn.Background = Brushes.Red;
btn.Content = "No";
WPF example – part 1
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation "
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
x:Class="SDKSample.MyWindow" Title="Window with Button" Width="250"
Height="100">
Same as main
<!-- Add button to window -->
Same as namespace
window
<Button Name="button1" Click="button_Click">Click Me!
</Button>
</Window>
• The x:Class associates these 2 elements of the project:
• XAML def'n of window (above)
• code-behind class (MyWindow) on next slide
• This example (parts 1 & 2) is from:
http://msdn.microsoft.com/en-us/library/aa970268(v=vs.110).aspx
WPF example –part 2
using System.Windows; // Window, RoutedEventArgs, MessageBox
namespace SDKSample
{ public partial class MyWindow : Window
{ public MyWindow()
{ // InitializeComponent call is required to merge the UI
// that is defined in markup with this class, including
// setting properties and registering event handlers
InitializeComponent();
}
void button1_Click(object sender, RoutedEventArgs e)
{ // Show message box when button is clicked
MessageBox.Show("Hello, from WPF app!");
}
}
}
Events
• WPF events are "routed"
• May traverse a hierarchy of handlers
• May be handled by more than 1 handler
• Last "desired" handler sets the "handled" property to "true"
• Stops all further handling
• "Source" property saves origin of event
• 3 types:
• Direct events – similar to Windows Forms events – no hierarchy traversal
• Bubbling events – start at the Source and travel UP the hierarchy to the Window
• Tunneling events - start at the Window and travel DOWN the hierarchy
• Prefixed with "Preview" (e.g.; PreviewMouseLeftButton)
• An event handler can handle events for > 1 control
• To specify this:
• Select the control
• Use the Events tab in the Properties window
• Reference: http://bit.ly/RoutedEvents
Commands
• Provide alternate ways of creating events
• Similar to MFC and Win32API
• Menu bars provide "labels" for actions
• Allows synch between command and program "state"
• "copy" can only be done if something is "selected"
• Invalid commands can be greyed-out
• Many standard commands built-in
•
•
•
•
Copy, Cut, Paste
Open, Save, Close, New
ToggleBold, ToggleItalic, ToggleUnderline
Play, Stop, Rewind
Resources
• Describe the objects your project uses
• Provides means to "bind" resources to code
• Two types of Resources
• Static
• Dynamic
• Two types of Resource Files:
• Linked
• External files
• .resx file includes only a relative path
• Embedded
• Inside the .resx file of the project
Adding Resources
• Right-click the Properties node under the project in Solution Explorer
• Click "Open"
• Click Add Resource button
• (top of the Resources page in Project Designer)
Sample text to Datagrid
Data source is created using an ObservableCollection of a custom class
in the window’s code-behind script
This is not always the best approach to take – you will usually be using
DataAdapters and DataTables to retrieve information from a database,
or external files
Setting the grid’s ItemSource property to inherit from the data context
creates the binding between grid & data.
After the collection is populated, set
Grid.DataContext = collection_name;
causes the user interface to update and display the grid content.
XAML & Code-behind
<DataGrid Name="myGrid" CanUserResizeColumns="True" CanUserAddRows="False"
CanUserSortColumns="True" IsReadOnly="True"
ItemsSource="{Binding}" />
using System; using System.Collections.ObjectModel; using System.Windows;
namespace Wpf_userlist
{ public class User
//our observable collection class
{
private String _n;
private int _n1;
public String name
// "name" will be bound to collection
{
get { return _n; }
set { _n = value; }
// value is set on next slide
}
public int int1
// "int1" will be bound to collection
{
get { return _n1; }
set { _n1 = value; }
}
}
Create Observable Collection
public partial class MainWindow : Window
{ public ObservableCollection User = new ObservableCollection();
public MainWindow()
{
InitializeComponent();
// next 2 lines to be replaced by file reading
data.Add(new User() {Name="Foreman", int1=1});
data.Add(new User() {Name ="Smith", int1=2});
myGrid.DataContext = User;
}
} // end of partial class MainWindow
} // end of program
Read a file
// Read a file and display it line by line.
System.IO.StreamReader myFile = new System.IO.StreamReader("c:\\test.txt");
while((line = file.ReadLine()) != null)
{
process_line(line); // move line into data array
}
OR
string[] lines = System.IO.File.ReadAllLines(@"C:\Users\test.txt");
myFile.Close();
Using a datagrid
• Here’s a really good tutorial on getting data into a datagrid.
http://www.c-sharpcorner.com/uploadfile/mahesh/datagrid-in-wpf/
But it uses "predefined" data. You need a file-read.
• Here’s a short example (lots of details omitted) from my own code:
private void process_line (String x)
{
string thename; String[] ints;
ints = x.Substring(position of 2nd quote+2).Split(',');
csvlist.Add (new csvrow() { name = thename, int1 = ints[0], int2=ints[1] });
// MessageBox.Show("name="+ csvlist[0].name);
}
• csvlist is a List of type csvrow, where csvrow is a C# class that specifies the
names of the columns of the datagrid.
• Split is a member that separates-out the elements of a string
• Process_line is called after each whole line of input is obtained
• Remember to instantiate everything:
• csvlist = new List<csvrow>();
• datagrid Userdata_DG1 = new DataGrid();