CPSC 481 Tutorial 7 More WPF Brennan Jones bdgjones@ucalgary.ca - - PowerPoint PPT Presentation

cpsc 481 tutorial 7
SMART_READER_LITE
LIVE PREVIEW

CPSC 481 Tutorial 7 More WPF Brennan Jones bdgjones@ucalgary.ca - - PowerPoint PPT Presentation

CPSC 481 Tutorial 7 More WPF Brennan Jones bdgjones@ucalgary.ca (based on tutorials by Alice Thudt, Fateme Rajabiyazdi, and David Ledo) Plan for Today More WPF material, examples, and coding exercises Mostly stuff that will be


slide-1
SLIDE 1

CPSC 481 – Tutorial 7

More WPF

Brennan Jones bdgjones@ucalgary.ca (based on tutorials by Alice Thudt, Fateme Rajabiyazdi, and David Ledo)

slide-2
SLIDE 2

Plan for Today

  • More WPF material, examples, and coding exercises
  • Mostly stuff that will be applicable to implementing your

vertical prototypes

slide-3
SLIDE 3

Reminder

Horizontal prototype due Monday Nov. 2 in lecture:

  • 1. Write-up – including redesign rational (i.e.,

changes from the first prototype), screen snapshots, and a grading sheet (from assignment handout)

  • 2. Horizontal prototype presentation freeze
  • Either email your slides to me

(bdgjones@ucalgary.ca) OR submit them on a USB along with your write-up.

slide-4
SLIDE 4

Horizontal Prototype Presentations

  • Tuesday, November 3 in tutorial (T03)
  • Monday, November 9 in tutorial (T01)
slide-5
SLIDE 5

More WPF!

slide-6
SLIDE 6

User Controls

  • Controls are interactive elements in WPF
  • Elements such as Buttons, TextBoxes, etc. are

Microsoft Controls

  • If you want to reuse specific elements in your

interface, you can create User Controls

  • User Controls can be composites of Microsoft

Elements

slide-7
SLIDE 7

User Controls

Create your own User Control

slide-8
SLIDE 8

Exercise

Create your own User Control, and try to add an instance of it to your MainWindow.xaml.

slide-9
SLIDE 9

Transitions

Create three buttons XAML

slide-10
SLIDE 10

Transitions

Create a user control

slide-11
SLIDE 11

Transitions

Name it

slide-12
SLIDE 12

Transitions

Fill it with content

slide-13
SLIDE 13

Transitions

Create two additional user controls and do the same.

slide-14
SLIDE 14

Transitions

Add a StackPanel to the Main Window Give it a name

slide-15
SLIDE 15

Transitions

Add the following code to your MainWindow.xaml.cs before the public MainWindow(){ … } constructor:

// Initialize user controls. UserControl1 page1 = new UserControl1(); UserControl2 page2 = new UserControl2(); UserControl3 page3 = new UserControl3();

slide-16
SLIDE 16

Transitions

Result:

slide-17
SLIDE 17

Exercise

Make it so that clicking the buttons at the top changes the current user control.

slide-18
SLIDE 18

Solution

Add the following click-event handlers:

private void page1Button_Click(object sender, RoutedEventArgs e) { stackPanel1.Children.Clear(); stackPanel1.Children.Add(page1); } private void page2Button_Click(object sender, RoutedEventArgs e) { stackPanel1.Children.Clear(); stackPanel1.Children.Add(page2); } private void page3Button_Click(object sender, RoutedEventArgs e) { stackPanel1.Children.Clear(); stackPanel1.Children.Add(page3); }

slide-19
SLIDE 19

User Controls – Exercise

Create a User Control for an Email that looks like this:

slide-20
SLIDE 20

Solution – User Control XAML

<Grid Background="White"> <Ellipse Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="100" Margin="10,10,0,0" Stroke="Black" VerticalAlignment="Top" Width="100"/> <Label Name="SenderText" Content="Sender: Brennan Jones" HorizontalAlignment="Left" Margin="125,19,0,0" VerticalAlignment="Top" FontWeight="Bold"/> <Label Name="BodyText" Content="Body of the email..." HorizontalAlignment="Left" Margin="125,50,0,0" VerticalAlignment="Top"/> <Canvas Name="DeleteGroup" HorizontalAlignment="Left" Height="25" Margin="401,10,0,0" VerticalAlignment="Top" Width="25" MouseDown="DeleteGroup_MouseDown"> <Ellipse Fill="Red" Height="25" Canvas.Left="0" Stroke="Black" Canvas.Top="0" Width="25"/> <Label Content="X" Canvas.Left="0" Canvas.Top="0" Foreground="White"/> </Canvas> </Grid>

slide-21
SLIDE 21

Exercise

  • Make the Sender a property that can be different in

each instance of an email.

  • When the delete Button is clicked, the email should

be removed from the view.

slide-22
SLIDE 22

Solution – User Control C#

public partial class Email : UserControl { private string sender; public string Sender { get { return sender; } set { sender = value; this.SenderText.Content = this.sender; } } private string body; public string Body { get { return body; } set { body = value; this.BodyText.Content = this.body; } } public Email() { InitializeComponent(); } private void DeleteGroup_MouseDown(object sender, MouseButtonEventArgs e) { (this.Parent as Panel).Children.Remove(this); } }

slide-23
SLIDE 23

Scroll Viewers

<ScrollViewer Height=“auto"> <StackPanel Height=“auto" Width=“auto"></StackPanel> </ScrollViewer>

slide-24
SLIDE 24

Exercise

  • Create a scroll viewer in your main window that shows 20

emails (using the Email User Control that you just created).

  • Create a for loop that initializes 20 Email User Controls.
  • To make it easy, make the Sender of each email “Sender “ + i
  • I.e., “Sender 1,” “Sender 2,” “Sender 3,” etc.
slide-25
SLIDE 25

Solution – Main Window C#

public MainWindow() { InitializeComponent(); for(int i = 0; i < 20; i++) { Email email = new Email(); email.Sender = "Sender " + i.ToString(); this.Emails.Children.Add(email); }

}

slide-26
SLIDE 26

Remaining Topics

Which of these do you want me to go over?

  • Transitions (Method 2)
  • Styles and Templates
  • List Boxes
  • Simple Animations
  • Click & Drag
  • Triggers
  • Image as a Button
  • Timer
slide-27
SLIDE 27

Transitions (Method 2)

  • 1. Create three User Controls. Name them:

MainMenu, Page1, and Page2.

  • 2. Add a Switcher.cs class to the project. This class

will handle switching between different User Controls.

slide-28
SLIDE 28

Transitions (Method 2)

using System.Windows.Controls; public static MainWindow pageSwitcher; public static void Switch(UserControl newPage) { pageSwitcher.Navigate(newPage); }

slide-29
SLIDE 29

Transitions (Method 2)

  • 3. Add the following code to MainWindow.xaml.cs

public MainWindow() { InitializeComponent(); Switcher.pageSwitcher = this; Switcher.Switch(new MainMenu()); } public void Navigate(UserControl nextPage) { this.Content = nextPage; }

slide-30
SLIDE 30

Transitions (Method 2)

  • 4. Design MainMenu, Page1, and Page2 to look like this:
slide-31
SLIDE 31

Transitions (Method 2)

  • 5. For MainMenu, Page1, and Page2, add the

following events:

private void Button_Click(object sender, RoutedEventArgs e) { Switcher.Switch(new MainMenu()); } private void Button_Click_1(object sender, RoutedEventArgs e) { Switcher.Switch(new Page1()); } private void Button_Click_2(object sender, RoutedEventArgs e) { Switcher.Switch(new Page2()); }

slide-32
SLIDE 32

Transitions (Method 2)

  • 6. If you ever want to save the state of a page while

transitioning (e.g., to save the contents of textboxes, the states of checkboxes etc.), keep the same User Control object. For example:

Page1 page1 = new Page1(); ... private void Button_Click_1(object sender, RoutedEventArgs e) { Switcher.Switch(page1); }

Always use this ‘Page1’ object

slide-33
SLIDE 33

Styles and Templates

Source (and excellent resource): http://www.codeproject.com/Articles/84630/WPF- Customize-your-Application-with-Styles-and-Con

slide-34
SLIDE 34

Styles and Templates

Start by creating a button

slide-35
SLIDE 35

Styles and Templates

Add this ‘Resources’ block

slide-36
SLIDE 36

Styles and Templates

Insert this code: This defines the style of buttons in your XAML. The button’s appearance changes

slide-37
SLIDE 37

Styles and Templates

You can also give it a key… …and set specific buttons to the particular style.

slide-38
SLIDE 38

Styles and Templates

You can create define Control Templates

  • These define how a control is drawn
slide-39
SLIDE 39

Styles and Templates

Example:

<UserControl.Resources> <Style x:Key="MyButtonStyle" TargetType="{x:Type Button}"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Button}"> <Border Name="fondoboton" BorderBrush="DarkGray" BorderThickness="5" CornerRadius="10,0,10,0" Background="LightGray"> <ContentPresenter Name="contenido" Content="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}"></ContentPresenter> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </UserControl.Resources>

slide-40
SLIDE 40

Styles and Templates

Result:

slide-41
SLIDE 41

Styles and Templates

You can also define a default background colour:

<UserControl.Resources> <Style x:Key="MyButtonStyle" TargetType="{x:Type Button}"> <Setter Property="Background" Value="Orange" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Button}"> <Border Name="fondoboton" BorderBrush="DarkGray" BorderThickness="5" CornerRadius="10,0,10,0" Background="{TemplateBinding Background}"> <ContentPresenter Name="contenido" Content="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}"></ContentPresenter> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </UserControl.Resources>

Add this line Add this

slide-42
SLIDE 42

Styles and Templates

Result:

slide-43
SLIDE 43

Styles and Templates

For a specific button, you can set the background colour to something other than the ‘default’, while keeping everything else the same as the template.

  • Without changing the template, change the

button’s XAML code to something like this:

<Button Style="{StaticResource MyButtonStyle}" Background="Red" Content="Button" HorizontalAlignment="Left" Margin="119,234,0,0" VerticalAlignment="Top" Width="75"/>

Background is ‘Red’

slide-44
SLIDE 44

Styles and Templates

Result:

slide-45
SLIDE 45

Exercise

Define a template for a button (like the one shown in the previous slides) that has a default border colour

  • f black, and create a button of that template that

has the border colour blue.

slide-46
SLIDE 46

Solution

<UserControl.Resources> <Style x:Key="MyButtonStyle" TargetType="{x:Type Button}"> <Setter Property="BorderBrush" Value="Black" /> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="{x:Type Button}"> <Border Name="fondoboton" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="5" CornerRadius="10,0,10,0"> <ContentPresenter Name="contenido" Content="{Binding Path=Content, RelativeSource={RelativeSource TemplatedParent}}"></ContentPresenter> </Border> </ControlTemplate> </Setter.Value> </Setter> </Style> </UserControl.Resources>

slide-47
SLIDE 47

Solution

Result:

slide-48
SLIDE 48

Solution (cont’d)

<Button Style="{StaticResource MyButtonStyle}" BorderBrush="Blue" Content="Button" HorizontalAlignment="Left" Margin="119,234,0,0" VerticalAlignment="Top" Width="75"/>

slide-49
SLIDE 49

Solution

Result:

slide-50
SLIDE 50

List Boxes

Drag a ListBox into the XAML

slide-51
SLIDE 51

List Boxes

Click to modify items

slide-52
SLIDE 52

List Boxes

Click to add Select ‘ListBoxItem’

slide-53
SLIDE 53

List Boxes

Change content

slide-54
SLIDE 54

List Boxes

Result:

slide-55
SLIDE 55

List Boxes

Can get the currently-selected index:

listbox1.SelectedIndex

slide-56
SLIDE 56

Exercise

  • Write code that changes the text in a textbox

whenever a listbox’s selection is changed.

slide-57
SLIDE 57

Solution – C#

Add ‘SelectionChanged’ event handler.

private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e) { textbox1.Text = (String)((ListBoxItem)listBox1.SelectedItem).Content; }

slide-58
SLIDE 58

Simple Animations

Insert an ellipse into your XAML

slide-59
SLIDE 59

Simple Animations

XAML code:

<Ellipse Name="ellipse1" Fill="#FFE82828" HorizontalAlignment="Left" Height="118" Margin="10,151,0,0" Stroke="Black" VerticalAlignment="Top" Width="127"/>

slide-60
SLIDE 60

Simple Animations

Add this code to the top of your C# file:

using System.Windows.Media.Animation;

Add this inside your user control class before the constructor:

private Storyboard myStoryboard;

slide-61
SLIDE 61

Simple Animations

Add this code to your user control constructor:

// animate fade in and fade out DoubleAnimation animation = new DoubleAnimation(); animation.From = 1.0; animation.To = 0.0; animation.Duration = new Duration(TimeSpan.FromSeconds(5)); animation.AutoReverse = true; animation.RepeatBehavior = RepeatBehavior.Forever; myStoryboard = new Storyboard(); myStoryboard.Children.Add(animation); Storyboard.SetTargetName(animation, ellipse1.Name); Storyboard.SetTargetProperty(animation, new PropertyPath(Ellipse.OpacityProperty)); // Use the Loaded event to start the Storyboard. ellipse1.Loaded += new RoutedEventHandler(myEllipseLoaded);

slide-62
SLIDE 62

Simple Animations

Add this function:

private void myEllipseLoaded(object sender, RoutedEventArgs e) { myStoryboard.Begin(this); }

slide-63
SLIDE 63

Exercise

  • Change the animation so that the width of the

ellipse is animated.

slide-64
SLIDE 64

Solution

// animate fade in and fade out DoubleAnimation animation = new DoubleAnimation(); animation.From = 120.0; animation.To = 240.0; animation.Duration = new Duration(TimeSpan.FromSeconds(5)); animation.AutoReverse = true; animation.RepeatBehavior = RepeatBehavior.Forever; myStoryboard = new Storyboard(); myStoryboard.Children.Add(animation); Storyboard.SetTargetName(animation, ellipse1.Name); Storyboard.SetTargetProperty(animation, new PropertyPath(Ellipse.WidthProperty)); // Use the Loaded event to start the Storyboard. ellipse1.Loaded += new RoutedEventHandler(myEllipseLoaded);

slide-65
SLIDE 65

Click & Drag

Create an ellipse Give it a name

slide-66
SLIDE 66

Click & Drag

Give the grid a name too

slide-67
SLIDE 67

Click & Drag

Add MouseDown Add MouseMove Add MouseUp

slide-68
SLIDE 68

Click & Drag

In your C# file:

bool captured = false; ... private void Ellipse_MouseDown_1(object sender, MouseButtonEventArgs e) { captured = true; } private void Ellipse_MouseUp_1(object sender, MouseButtonEventArgs e) { captured = false; } private void Ellipse_MouseMove_1(object sender, MouseEventArgs e) { if (captured) { Thickness margin = ellipse1.Margin; margin.Left = e.GetPosition(_mainGrid).X - (ellipse1.Width / 2); margin.Top = e.GetPosition(_mainGrid).Y - (ellipse1.Height / 2); ellipse1.Margin = margin; } }

slide-69
SLIDE 69

Triggers

Source (and excellent resource): http://www.wpf- tutorial.com/styles/trigger-datatrigger-event-trigger/

slide-70
SLIDE 70

Triggers

  • Allow you to change the value of a given property
  • nce a certain condition changes
  • Allow you to do this entirely in XAML
  • Three types:
  • 1. Property trigger
  • 2. Data trigger
  • 3. Event trigger
slide-71
SLIDE 71

Triggers

Property trigger

  • Defined by <Trigger> element.
  • Watches a specific property on the owner control,

and whenever that property has a specific value, it changes other properties.

slide-72
SLIDE 72

Triggers

Property trigger example

<TextBlock Text="Hello, styled world!" FontSize="28" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock.Style> <Style TargetType="TextBlock"> <Setter Property="Foreground" Value="Blue"></Setter> <Style.Triggers> <Trigger Property="IsMouseOver" Value="True"> <Setter Property="Foreground" Value="Red" /> <Setter Property="TextDecorations" Value="Underline" /> </Trigger> </Style.Triggers> </Style> </TextBlock.Style> </TextBlock>

slide-73
SLIDE 73

Triggers

Property trigger example

  • Result:
  • Underlines and colours the text red on mouse-over.
slide-74
SLIDE 74

Triggers

Data trigger

  • Defined by <DataTrigger> element.
  • Watches a specific property that can be anywhere

(not specifically on the owner control), and whenever that property has a specific value, it changes other properties.

slide-75
SLIDE 75

Triggers

Data trigger example

<CheckBox Name="cbSample" Content="Hello, world?" /> <TextBlock HorizontalAlignment="Center" Margin="0,20,0,0" FontSize="48"> <TextBlock.Style> <Style TargetType="TextBlock"> <Setter Property="Text" Value="No" /> <Setter Property="Foreground" Value="Red" /> <Style.Triggers> <DataTrigger Binding="{Binding ElementName=cbSample, Path=IsChecked}" Value="True"> <Setter Property="Text" Value="Yes!" /> <Setter Property="Foreground" Value="Green" /> </DataTrigger> </Style.Triggers> </Style> </TextBlock.Style> </TextBlock>

slide-76
SLIDE 76

Triggers

Data trigger example

  • Result:
  • Changes the text to “Yes!” and the text colour to green

when the checkbox is checked.

slide-77
SLIDE 77

Triggers

Event trigger

  • Defined by <EventTrigger> element.
  • Triggers in response to an event being called.
  • Triggers exactly once that event is called.
slide-78
SLIDE 78

Triggers

Event trigger example

<TextBlock Name="lblStyled" Text="Hello, styled world!" FontSize="18" HorizontalAlignment="Center" VerticalAlignment="Center"> <TextBlock.Style> <Style TargetType="TextBlock"> <Style.Triggers> <EventTrigger RoutedEvent="MouseEnter"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <DoubleAnimation Duration="0:0:0.300" Storyboard.TargetProperty="FontSize" To="28" /> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> ...

slide-79
SLIDE 79

Triggers

Event trigger example (cont’d)

... <EventTrigger RoutedEvent="MouseLeave"> <EventTrigger.Actions> <BeginStoryboard> <Storyboard> <DoubleAnimation Duration="0:0:0.800" Storyboard.TargetProperty="FontSize" To="18" /> </Storyboard> </BeginStoryboard> </EventTrigger.Actions> </EventTrigger> </Style.Triggers> </Style> </TextBlock.Style> </TextBlock>

slide-80
SLIDE 80

Triggers

Event trigger example

  • Result:
  • Animation enlarges the text on mouse-over, and shrinks

it back to its original size on mouse-leave.

slide-81
SLIDE 81

Image as Button

Exercise: Create a button that displays as an image.

slide-82
SLIDE 82

Image as Button

Solution:

<Grid> <Button Background="Transparent" HorizontalAlignment="Left" Margin="117,84,0,0" VerticalAlignment="Top" Width="361" Height="231"> <Image Name="img1" Stretch="Fill" Source="Testimg.png" Margin="10"/> </Button> </Grid>

slide-83
SLIDE 83

Timer

  • We are going to make use of a DispatchTimer.
  • Make sure you are using the Threading

namespace.

  • Add a TextBlock on your code. We will change the

value every time the timer ticks.

slide-84
SLIDE 84

XAML

<Grid Name="Grid"> <TextBlock Name=”timerText" FontSize="48” HorizontalAlignment="Center" VerticalAlignment="Center" /> </Grid>

slide-85
SLIDE 85

C#

using System.Windows.Threading; public void DispatcherTimerSample() { InitializeComponent(); DispatcherTimer timer = new DispatcherTimer(); timer.Interval = TimeSpan.FromSeconds(1); timer.Tick += timer_Tick; timer.Start(); } void timer_Tick(object sender, EventArgs e) { timerText.Content = DateTime.Now.ToLongTimeString(); }