Event Handling C# Help

WPF classes define events where you can add your handlers. For example, you can add MouseEnter, MouseLeave, MouseMove, Click, and the like. This is based on the events and delegates mechanism on .NET.covers the event and delegate architecture of .NET, With WPF,you can assign the event handler either with XAML or in the code behind. With buttonl the XMLattribute Click is used to assign the method button_Click to the click event. button 2 has no event handler assigned in XAML:

<Button Name=”buttonl” Click=”button_Click”>Button l</Button>
<Button Name=”button2″> Button 2</Button>

The Click event for button2 is assigned in the code behind by creating an instance of the delegate RoutedEventHandler and passing the method button_Click to the delegate. The method button_ Click () that is invoked from both buttons has arguments as defined by the RoutedEventHandler delegate:

InitializeComponent();
button2.Click += button_Click;
public Windowl()
(
)
void button_Click(object sender, RoutedEventArgs e)
(
MessageBox.Show(“Click Event”);

The event-handling mechanism for WPF is based on .NETevents but extended with bubbling and tunneling features. As you have already learned, a But ton can contain graphics, list boxes, another button, and so on. What happens if a CheckBox is contained inside a Button and you click the CheckBox? Where should the event arrive? The answer is that the event is bubbled, First, the Click event arrives with the CheckBox, and then it bubbles up to the Button, This way, you can handle the Click event for all elements that are inside the Button with the Button.

Some events are tunneling events; others are bubbling events, A tunneling event first arrives with the outer element and tunnels to the inner elements, Bubbling events start with the inner element and bubble to the outer elements, Tunneling and bubbling events are usually paired. Tunneling events are prefixed with preview, for example, PreviewMouseMove, This event tunnels from the outer controls to the inner controls. After the PreviewMouseMove event, the MouseMovement occurs, This event is a bubbling event that goes from the inner to the outer controls.

You can stop tunneling and bubbling by setting the Handled property of the event argument to true, The Handled property is a member of the RoutedEventArgs class. All event handlers that participate with the tunneling and bubbling facility have an event argument of type RoutedEventArgs or a type that derives from RoutedEventArgs.

If you stop the tunneling of an event by setting the Handled property to true, then the bubbling event that follows the tunneling event will not happen anymore.

Styles, Templates, and Resources

You can define.the look and feel of the WPF elements by setting properties, such as FontSize and Background, with the Button element as shown:

StackPanel>
<Button Name=’buttonl’ Width=’150′ FantSize=’12’ Background=’AliceBlue’>
Click Me!
</Button>
StackPanel>

Instead of defining the look and feel with every element, you can define styles that are stored with resources, To completely customize the look for controls, you can use templates and store them into resources:

Styles

To define styles, you can use a Style element containing Setter elements. With the Setter, you specify the Property and the val ue of the style, for example, the property But ton. Background and the value AliceBlue.

To assign the styles to specific elements, you can assign a style to all elements of a type or use a key for the style, To assign a style to all elements of a type, use the TargetType property of the Style and assign it to a Button by specifying the x: Type markup extension {x:Type Button}.

In the following XAML code, but ton2, which doesn’t haw a style defined with the element properties, gets the style that is defined for the But tor. type. For button, the Style property is set with the StaticResource markup extension to {StaticResource ButtonStyle}, whereas ButtonStyle specifies the key value of the style resource defined earlier, so button 3 has an aliceblue background.

<Button Narne=”button2″ Width=”150″>Click Me!</Button>
<Button Narne=”button3″ Width=”150″ Style=” {StaticResource ButtonStyle}”>
Click Me, Too!
< Button>

Instead of setting the Background of a button to just a single value, you can also do more. You can set the Background property to a LinearGradientBrush with a gradient color definition as shown:

button4 has the fancy style with the linear gradient cyan color applied:

<Button Narne=”button4″ Width=”200′ Style=”{StaticResource FancyButtonStyle}”>
Fancy!
</Button>’

You can see the results of all these buttons styled in Figure 34-18.

Figure 34-18

Figure 34-18

Resources

As you have seen with the styles sample, usually styles are stored within resources. You can define any element within a resource, For example, the brush created earlier for the background style of the button can itself be defined as a resource, so you can use it everywhere a brush is required.

The following example defines a LinearGradientBrush with the key name MyGradientBrush inside the StackPanel resources, buttonl assigns the Background property by using a StaticResource markup extension to the resource MyGradientBrush. Figure 34-19 shows the output from this XAML code:

Figure 34-19

Figure 34-19

Here, the resources have been defined with the StackPanel, In the previous example, the resources were defined with the Windowelement, The base class FrarneworkElement defines the property Resources of type ResourceDictionary, That’s why resources can be defined with every class that is derived from the FrarneworkElement-any WPF element.

Resources are searched hierarchically. If you define the resource with the window, it applies to every child element of the window. If the window contains a Grid, and the Grid contains a StackPanel, and if you define the resource with the StackPanel, then the resource applies to every control within the StackPanel. If the StackPanel contains a Button, and you define the resource just with the Button, then this style is valid just for the button.

In regard to hierarchies, you need to pay attention if you use the TargetType without a Key for styles, If you define a resource with the Canvas element and set the TargetType for the style to apply to TextBox elements, then the style applies to all TextBox elements within the Canvas. Tile style even applies to TextBox elements that are contained in a ListBox when tile ListBox is in the Canvas.

If you need the same style for more than one Window, then you can define the style with the application, In a Visual Studio WPF project, the file App  xaml is created for defining global resources of the application, The application styles are valid for every window of the application, Every element can access resources that are defined with the application, If resources are not found with the parent window, then the search for resources continues with the Application.

To do this, buttonl doesn’t have a background specified, but the Click event is assigned to the method buttonl_Click.

With the implementation of buttonl_Click (), the FindResource () method is used on the Button that was clicked. Then a search for the resource MyGradientBrush happens hierarchically, and the brush is applied to the Background property of the control.

public void buttonl_Click(object sender, RoutedEventArgs e)
(
Control ttrl = sender as Control;
ctrl.Background =
ctrl.FindResource(“MyGradientBrush”) as Brush;

If FindResource () does not find the resource key, then an exception is thrown, If you don’t know for sure if the resource ·is available, then you can use the method TryFindResource () instead, TryFindResource () returns null if the resource is not found.


Dynamic Resources

With the StaticResource markup extension, resources are searched at load time. If the resource changes while the program is running, then you should use the DynamicResource markup extension instead.

The next example is using the same resource as defined previously. buttonl uses the resource as a StaticResource, and button3 uses the resource as a DynamicResource with the DynamicResource markup extension, button2 is used to change the resource programmatically. It has the Click event handler method button2_Click assigned.

The implementation of but ton2_Click () clears the resources of the StackPanel and adds a new resource with the same name, MyGradientBrush, This new resource is very similar to the resource that is defined in XAML code; it just defines different colors.

If you run the application and change the resource dynamically by clicking the third button, then button4 immediately gets the new resource. button1, which was defined with the StaticResource, keeps the old resource that was loaded.

The DynamicResource requires more performance than the StaticResource because the resource is always loaded when needed, Use DynamicResQurce only with resources where you expect changes during runtime.

Triggers

With triggers you can change the look and feel of your controls dynamically because of some events or some property value.changes. For example, when the user moves with the mouse over a button, the button can change its look. Usually, you need to do this with the C# code. With WPF, you can also do this with XAML, as long as only the VI is influenced.

The Style class has a Triggers property where you can assign property triggers, The following example includes two TextBox elements inside a Canvas panel, With the Wlndow resources, a style TextBoxStyle is defined that is referenced by the TextBox elements using the Style property, The TextBoxStyle specifies that the Background is set to LightBlue and the FontSize to. This is the style of the TextBox elements when the application is started, using triggers, the style of the controls change, The triggers are defined within the Style. Triggers element, using the Trigger element, One trigger is assigned to the property is MouseOver; the other trigger is assigned to the property is KeyboardFocused, Both of these properties are defined with the TextBox class that the style applies to. If is MouseOver has a value of true, then the trigger fires and sets the Background property to Red and the FontSize property to 22, If the TextBox has a keyboard focus, then the property IsKeyboardFocused is true, and the second trigger fires and sets the Background property of the TextBox to Yellow.

You don’t need to reset the property values to the original values when the reason for the trigger is not valid anymore. For example, you don’t need to define a trigger for is MouseOver=true and is MouseOver=false, As soon as the reason for the trigger is no longer valid, the changes made by the trigger action are reset to the original values automatically.

Figure 34-21 shows the trigger sample application, where the first text box has the keyboard input focus, and the second text box has the default values of the style for the background and font size.

Figure 34-21

Figure 34-21

When using property triggers, it is extremely easy to change the look of controls, fonts, colors, opacity, and the like. When the mouse moves over them, the keyboard sets the focus – not a single line of programming code is required.

The Trigger class defines the following properties to specify the trigger action.

Property triggers are just one type of trigger possible in WPF. Another trigger type is event triggers. Event triggers are discussed later in this chapter along with animations.

Templates

You have already seen that a But ton control can have any content. The content can be simple text, but you can also add a Canvas element, which can contain shapes, You can add a Grid, or video to the button. However, there is even m~re than that you can do with a button!

In WPF, the functionality of controls is completely separate from their look and feel, A button has a default look, but you can completely customize that look as you like with templates.

WPF gives you several template types that derive from the base class FrameworkTemplate.

The next sample shows several buttons, and later, list boxes are customized step by step, so you can see the intermediate results of the changes. First, start with two very simple buttons in which the first button doesn’t have a style at all, The second button references the style buttonStyle With changes to the Background and the FontSize, You can see this first result in Figure 34-22.

Figure 34-22

Figure 34-22

Figure 34-23

Figure 34-23

The button now has a completely different look. However, the content that is defined with the button itself is missing in Figure 34·23. The template created previously must be extended. The first rectangle in the template now has its Fill property set to {TemplateBinding Background}, The TemplateBinding markup extension enables a control template to use content from the templated control. Here, the rectangle is filled with the background that is defined with the button, button3 defines a yellow background, which is combined with the background from the second rectangle of the control template, After the definition of the second rectangle, the element ContentPresenter is used, This element takes the content from the templated control and places it as defined – here on both rows, as grid RowSpan is set to 2, If a ContentPresenter is defined, then the Target Type with the Control Template must also be set, The content is positioned by setting the HorizontalArignment, VerticalAlignment, and Margin properties to values defined by the button itself by using TemplateBinding markup extensions. With the Control Template you can also define triggers, as previously shown within resources, Figure 34-24 shows the new outcome of the button, including the content and the background combined with the template.

Figure 34-24

Figure 34-24

Let’s make an even fancier button by using transparent features. The style Gel Button sets the properties Background, Height, Foreground and Margin, and the Template, The template is the most interesting aspect with this style The template specifies a Grid with just one row and one column.

Inside this cell, you can find a rectangle with the name GelBackground, This rectangle has rounded comers and a linear gradient brush for the stroke, The rounded comers are defined by the RadiusX and RadiusY settings, The stroke that surrounds the rectangle is very thin because the Stroke Thickness ts set to 0.35.

The second rectangle, GelShine, is just a small rectangle with a height of 15 pixels, and because of the Margin settings, it is visible within the first rectangle. The stroke is transparent, so there is no line surrounding the rectangle, This rectangle just uses a linear gradient fill brush, which goes from a light, partly transparent color to full transparency. This gives the rectangle a shimmering effect.

After the two rectangles, there is a ContentPresenter element that defines alignment for the content and takes the content from the button to display.

Such a styled button now looks very fancy on the screen. However, there is no action if the mouse is clicked or the mouse moves over the button. With a template-styled button, you must have triggers for the button to appear differently in response to mouse clicks. The property trigger, is MouseOver, defines a new value for the Rectangle. Fill property with a different color for the radial gradient brush, The rectangle that gets the new fill is referenced with the Target Name property, The property trigger, Is Pressed, is very similar; here, simply other radial gradient brush colors are used to fill the rectangle. You can see a button that references the style GelButton in Figure 34-25. Figure 34-26 shows the same button while the mouse moved over it where you can see the effect of the radial gradient brush.

Figure 34-25

Figure 34-25

Figure 34-26

Figure 34-26

Instead of having a rectangular button, an ellipse can be used as a button. In the next example, you can also see how one style can be based on another style.

The style RoundedGelButton can be based on the style GelButton by setting the BasedOn property with the Style element, If one style is based on another style, then the new style gets all,settings from the base style unless the settings are redefined, For example, the RoundedGelButtonStyle gets the Foreground and margin settings from the GelButton because these settings are not redefined. If you
change a setting in a base style, then all styles that are based on the style automatically get the new values.

The Height and Template properties are redefined with the new style. Here, the template defines two Ellipse elements instead of rectangles, The outer ellipse Gel Background defines a black ellipse with a gradient stroke around it, The second ellipse is smaller with a small margin (5) at the top and a large margin (50) at the bottom, This ellipse again has a linear gradient brush that goes from a light color to transparent and specifies the shine effect, Again, there are triggers for IsMouseOver and ISPressed that change the value of the Fill property for the first ellipse.

You can see the new button based on the RoundedGelButton style – and it is still a button – in Figure 34-27.

Figure 34-27

Figure 34-27

Styling a ListBox

Changing a style of a button or a label is a simple task, How about changing the style of an element that contains a list of elements, For example, how about changing a ListBox? Again, a list box has behavior and a look, It can display a list of elements, and you can select one or more elements from the list, For the behavior, the ListBox class defines methods, properties, and events. The look of the ListBox is separate from its behavior, The ListBox element has a default look, but you can change this look by creating a template.

To display some items-in the list, the country class has been created to represent the name and flag with a path to an image, The class Country defines the Name and ImagePath properties, and it has an overridden To String () method for a default string representation:

The static class Countries returns a list of a few countries that will be displayed:

Inside the code-behind file in the constructor of the Windowl class, the DataContext property of the Window! instance is set to the list of countries that is returned from the method Countries .GetCountries () The DataContext property is a feature for data binding.

public partial class Windowl : System.Windows.Window
{
InitializeComponent();
this.DataContext = Co~ntries.GetCountries();
public windowl ()
(

Within the XAML code, the List Box named country List is defined. country List doesn’t have a different style. It uses the default look from the List Box element, The property Items Source is set to the Binding markup extension, which is used by data binding. From the code behind, you have seen that the binding is done to an array of Country objects. Figure 34-28 shows the default look of the List Box, By default, just tile names of the countries returned by the To String () method are displayed in a simple list.

Figure 34-28

Figure 34-28

The Country objects do have both the name and the flag in the object. Of course, you can also display both values in the list box. To do this, you need to define a template.

The ListBox element contains ListBoxItem elements. You can define the content for an item with the ItemTemplate, The style listBoxStylel defines an ItemTemplate with a value of a DataTemplate, A DataTemplate is used to bind data to elements. You can use the Binding markup extension with DataTemplate elements.

The DataTemplate contains a grid with three columns, The first column contains the string Country The second column contains the name of the country, The third column contains the flag for the country, Because the country names have different lengths, but the view should be the same size for every country name, the SharedSizeGroup property is set with the second column definition, This shared size information for the column is used only because the property Grid, is SharedSizeScope is also set.

After the column and row definitions, you can see two TextBlock elements. The first TextBlock element contains the text Country, The second TextBlock element binds to the Name property that is defined in the Country class.

The content for the third column is a Border element containing a Grid, The Grid contains a Rectangle with a linear gradient brush and an Image element that is bound to the ImagePath property of the Country class. Figure 34-29 shows the countries in a ListBox with completely different output than before.

Figure 34-29

Figure 34-29

It is not necessary that a ListBox have items that follow vertically, one after the other, You can give the user a different view with the same functionality. The next style, listBoxStyle2, defines a template in which the items are shown horizontally with a scroll bar.

In the previous example, only an Iternalplate was created to define how the items should look in the default ListBox, Now, a template is created to define a different ListBox, The template contains a Control Template element to define the elements of the ListBox, The element is now a ScrollViewer – a view with a scroll bar- that contains a StackPanel. As the items should now be listed horizontally, the orientation of the StackPanel is set to Horizontal. The stack panel will contain the items that are defined with the ItemsTemplate. As a result, the is Items Host of the StackPanel element is set to true, isItemsHost is a property that is available with every Panel element that can contain a list of items.

The Item Template defines the look for the items in the stack panel. Here, a grid with two rows is created. The first row contains Image elements that are bound to the ImagePath property, The second row contains TextBlock elements that are bound to the Name property.

Figure 34-30 shows the ListBox styled with listBoxStyle2 where the scroll bar appears automatically when the view is too small to display all items in the list.

Figure 34-30

Figure 34-30

Certainly you see the advantages of separating the look of the controls from their behavior, You may already have many ideas about how you can display your items in a list that best fits the requirements your application, Perhaps you just want to display as many items as will fit in the window, position them horizontally, and then continue to the next line vertically. That’s where a WrapPanel comes And, of course, you can have a WrapPanel inside a template for a ListBox, as shown in listBoxStyle, Figure 34-31 shows the result of using the WrapPanel.

Figure 34-31

Figure 34-31

Posted on November 3, 2015 in Windows Presentation Foundation

Share the Story

Back to Top