CPSC 481 – Week #7 Sowmya Somanath

Preview:

DESCRIPTION

Reminder Wednesday Nov 4 in tutorial (15 min each group) – T04: Horizontal prototype presentation Friday Nov 6 in tutorial (15 min each group) – T02: Horizontal prototype presentation

Citation preview

CPSC 481 – Week #7Sowmya Somanath

ssomanat@ucalgary.ca

ReminderMonday Nov 2 in class – 1. Write-up – redesign rational (i.e. changes from first prototype)2. Screen snapshots3. Grading sheet from handout4. Horizontal prototype presentation freeze

Either email your slides to me (ssomanat@ucalgary.ca) OR submit them on a USB along with your write-up.

Reminder• Wednesday Nov 4 in tutorial (15 min each group) – T04: Horizontal prototype presentation

• Friday Nov 6 in tutorial (15 min each group) –T02: Horizontal prototype presentation

Plan for TodayMore WPF – useful for implementing vertical prototype.Please download Week 7 slides from: http://pages.cpsc.ucalgary.ca/~ssomanat/CPSC481.htm

User Controls

User Controls• User controls pack a set of UI elements.• Useful when repeating same UI patterns• Instead of copy pasting code, you can re-use user controls.

User Controls1. Add a user control to your class. Name it UserControlDemo

User Controls2. Add Elements to your user control<Grid> <Label Content="I am the User Control" HorizontalAlignment="Left" Margin="19,35,0,0" VerticalAlignment="Top" Height="40" Width="271" FontWeight="Bold" FontSize="24"/> <Button Content="OK" HorizontalAlignment="Left" Height="50" Margin="35,117,0,0" VerticalAlignment="Top" Width="223" FontWeight="Bold"/> <Button Content="CANCEL" HorizontalAlignment="Left" Height="53" Margin="35,185,0,0" VerticalAlignment="Top" Width="223" FontWeight="Bold"/> </Grid></UserControl>

User Controls

3. Add below code to MainWindow.xaml

<Grid Name="grid1"> <Grid.RowDefinitions> <RowDefinition Height="40"/> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <Button Name="button1" Grid.Row="0" Content="Show User Control" Click="button1_Click"/></Grid>

User Controls

4. Add below code to MainWindow.cs

private void button1_Click(object sender, RoutedEventArgs e) { UserControlDemo ucdemo = new UserControlDemo(); Grid.SetRow(ucdemo, 1); grid1.Children.Add(ucdemo); }

User Control and Transitions:

Navigation Method

1. Create 3 user controls. Name them: MainMenu, Page 1 and Page 22. Add a Switcher.cs to the project – This class will handle switching between different

user controls

using System.Windows.Controls;

public static MainWindow pageSwitcher;

public static void Switch(UserControl newPage) { pageSwitcher.Navigate(newPage); }

You will need this to use Navigate() method

3. Add the following code to MainWindow.cs

public MainWindow() { InitializeComponent(); Switcher.pageSwitcher = this; Switcher.Switch(new MainMenu()); }

public void Navigate(UserControl nextPage) { this.Content = nextPage; }

4. Design MainMenu, Page 1 and Page 2 to look like this:

5. For MainMenu, Page 1 and Page 2 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()); }

User Control and Transitions: Excercise1

Don’t duplicate this

Solution <Grid Name="grid1"> <Grid.RowDefinitions> <RowDefinition Height="40"/> <RowDefinition Height="auto"/> </Grid.RowDefinitions> <Grid.ColumnDefinitions>

</Grid.ColumnDefinitions> <Button Name="button1" Grid.Column="0" Content="BACK" Margin="0,0,305,0" Click="button1_Click"/> <Button Name="button2" Grid.Row="0" Content="NEXT" Margin="292,0,0,0"

Click="button2_Click"/> <StackPanel Name="stack1" Grid.Row="1"></StackPanel> </Grid>

Solution private void button1_Click(object sender, RoutedEventArgs e) {

Next _next = new Next(); stack1.Children.Clear(); stack1.Children.Add(_next); }

private void button2_Click(object sender, RoutedEventArgs e) { Back _back = new Back(); stack1.Children.Clear(); stack1.Children.Add(_back); }

User Control and Scroll Viewers:

Excercise2

Create a user control for an email that looks like this:

Solution<Grid> <Grid.ColumnDefinitions> <ColumnDefinition Width="389*"/> <ColumnDefinition Width="234*"/> </Grid.ColumnDefinitions>

<Ellipse Fill="#FFF4F4F5" HorizontalAlignment="Left" Height="89" Margin="23,32,0,0" Stroke="Black" VerticalAlignment="Top" Width="89"/>

<Label x:Name="SenderTextblock" Content="Sender" HorizontalAlignment="Left" Height="42" Margin="127,32,0,0" VerticalAlignment="Top" Width="417" Grid.ColumnSpan="2"/>

<Label Content="Body of the email" HorizontalAlignment="Left" Height="42" Margin="127,62,0,0" VerticalAlignment="Top" Width="417" Grid.ColumnSpan="2"/>

<Canvas x:Name="DeleteGroup" Margin="364,12,209,95" Grid.ColumnSpan="2"> <Ellipse Fill="#FFB61D1D" HorizontalAlignment="Left" Height="50" Stroke="Black"

VerticalAlignment="Top" Width="50"/> <Label Content="X" HorizontalAlignment="Left" Height="50" VerticalAlignment="Top" Width="40"

FontSize="24" FontWeight="Bold" Canvas.Left="10" Foreground="White"/> </Canvas>

</Grid>

Create a scroll viewer in MainWindow.xaml:

Solution

<Grid> <ScrollViewer Height="auto"> <StackPanel Name="Emails" Height="auto" Width="auto"></StackPanel> </ScrollViewer>

</Grid>

• 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.

• Use the scroll viewer in your main window to show 20 emails (using the Email User Control you created)

---- Create a for loop that initializes 20 Email User Controls. ---- To make it easy, initialze the Sender of each email to “Sender” + I

e.g. Sender 0, Sender 1….

Solutionpublic partial class Email : UserControl { private string name; public string Name { get { return name; } set { name = value; this.SenderTextblock.Content = this.name; } }

public Email() { InitializeComponent(); this.DeleteGroup.MouseLeftButtonDown += DeleteGroup_MouseLeftButtonDown; }

void DeleteGroup_MouseLeftButtonDown(object sender, MouseButtonEventArgs e) { (this.Parent as Panel).Children.Remove(this); }

}

Solution

public MainWindow() {

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

}

Styles and Templates: Button

<Window.Resources> <!--Wpf Style and Template--> <!--Changing Button style--> <Style x:Key="myButtonStyle" TargetType="Button"> <Setter Property="Template"> <Setter.Value> <ControlTemplate TargetType="Button"> <!--Change corner radius values to change shape--> <Border Name="border" BorderBrush="DarkGray" BorderThickness="5" CornerRadius="30,0,66,0" Background="Brown"> <ContentPresenter HorizontalAlignment="Center" VerticalAlignment="Center"

Name="buttonpresenter"> </ContentPresenter> </Border> <!--Trigger for mouse event--> <ControlTemplate.Triggers> <Trigger Property="IsMouseOver" Value="true"> <Setter TargetName="border" Property="Border.CornerRadius"

Value="30,10,20,10"></Setter> </Trigger> <Trigger Property="IsMouseOver" Value="false"> <Setter TargetName="border" Property="Background“

Value="Gray"></Setter> </Trigger>

</ControlTemplate.Triggers></ControlTemplate>

</Setter.Value> </Setter> </Style></Window.Resources>

Give the style a key you can refer it by

Create this as a resource – window/ user control

<Grid> <Button Style="{StaticResource myButtonStyle}" Content="Button" HorizontalAlignment="Left" Height="154" Margin="54,59,0,0" VerticalAlignment="Top"

Width="396" Click="Button_Click"/></Grid>

• Control Template defines how a control is drawn• Can also include a setter property that can be changed:

<Style x:Key="myButtonStyle" TargetType="Button"> <Setter Property="Background" Value="Orange"/> <Setter Property="Template">

<ControlTemplate TargetType="Button"> <!--Change corner radius values to change shape--><Border Name="border" BorderBrush="DarkGray" BorderThickness="5" CornerRadius="30,0,66,0" Background="{TemplateBinding Background}">

<Button Style="{StaticResource myButtonStyle}" Content="Button" HorizontalAlignment="Left" Height="154" Margin="54,59,0,0" VerticalAlignment="Top" Width="396" Background="Red" Click="Button_Click"/>

Style and Template: Excercise3

Define a template for a button that has default border color of black. Create a button instance that uses the template but changes border color to blue.

Solution <Setter Property="BorderBrush" Value="Black"/>

<Border Name="border" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="5" CornerRadius="30,0,66,0">

<Button Style="{StaticResource myButtonStyle}" Content="Button" HorizontalAlignment="Left" Height="154" Margin="54,59,0,0" VerticalAlignment="Top" Width="396" BorderBrush="Blue" Background="Red" Click="Button_Click"/>

List Boxes

Drag a ListBox into the XAML

List Boxes

List Boxes

Click to modify items

List Boxes

Click to addSelect ‘ListBoxItem’

List Boxes

Change content

• Can get the currently-selected index:listbox1.SelectedIndex

ListBox: Excercise4

• Create a listbox like below and change TextBox content based on listbox selection.

• Add ‘SelectionChanged’ event handler.

Solution

private void ListBox_SelectionChanged(object sender, SelectionChangedEventArgs e) { textbox1.Text = (String)((ListBoxItem)listbox1.SelectedItem).Content;

}

Simple Animation

Add an ellipse to your xaml

Simple animations

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

Simple animation

• 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;

Simple animation // 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);

Simple animation

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

Simple animations: Excercise5

Change the animation so that the width of the ellipse is animated.

Solution// animate change width 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));

Mouse based Interactions

Add an ellipse to your xaml

Click and Drag

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

Click and Drag

• Add MouseDown, MouseMove and MouseUp events to the ellipse

Drag and Move bool captured = false;

private void ellipse1_MouseDown(object sender, MouseButtonEventArgs e) { captured = true;

}private void ellipse1_MouseMove(object sender, MouseEventArgs e) { if (captured) { Thickness margin = ellipse1.Margin; margin.Left = e.GetPosition(grid1).X - (ellipse1.Width / 2); margin.Top = e.GetPosition(grid1).Y - (ellipse1.Height / 2); ellipse1.Margin = margin; }

}private void ellipse1_MouseUp(object sender, MouseButtonEventArgs e) { captured = false;

}

Triggers

Triggers• Allow you to change the value of a given property once a certain

condition changes• Allow you to do this entirely in XAML

• Three types:1. Property trigger2. Data trigger3. Event trigger

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.

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>

Property trigger example• Result:• Underlines and colours the text red on mouse-over.

Data Triggers• 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.

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>

TriggersData trigger example• Result:• Changes the text to “Yes!” and the text colour to green when the checkbox is

checked.

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

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>

...

Event Trigger example...

<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>

Event Trigger• Result:• Animation enlarges the text on mouse-over, and shrinks it back to its original

size on mouse-leave.

Image as a ButtonExercise: Create a button that displays as an image.

Image as a ButtonSolution:<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>