In this article I present a code from the book “Pro WPF 4.5. in C#“, which I consider useful and interesting. This example has impressed me with its structure – it simply gives good practises for creation of 23 different controls within XAML. Once you run the example, you get the following window:
You may click on any button, in order to check the control and its execution. These are the options:
1. Embedded Font
2. Gdi Text Rendering
3. Buttons With Content
4. Button With Shape
5. Label Test
6. Radio Button Groups
7. Tooltips
8. Popup Text
9. Scrollable Text Box Column
10. Logical Scrolling
11. Graphical Tab Titles
12. Expandable Content
13. MultiDirectional Expanders
14. Expandable Scrollable Content
15. Text Box Test
16. Custom Spell Checker
17. Image List
18. Check Box List
19. Combo Box Test
20. Slider Test
21. Sliders Compared
22. Indeterminate Progress Bar
23. Date Controls
1. Embedded Font
Simply we use a font, which is available in the folder of the application. In order to embed the fount we use the command “./#Bayern”. The, the name of the file, where the font is present is “bayern.ttf”. The code in XAML looks like this:
1 2 3 4 |
<Grid> <Label Name="tst" FontSize="20" FontFamily="./#Bayern" >This is an embedded font</Label> </Grid> |
2. Gdi Text Rendering
Back to the list
This example simply shows us how the XAML what is it when we have ” TextOptions.TextFormattingMode=”Display” ” and when we do not have it. The XAML code looks like this:
1 2 3 4 5 6 7 8 9 10 |
<StackPanel Margin="10"> <TextBlock FontSize="12" Margin="5"> This is a Test. Ideal text is blurry at small sizes. </TextBlock> <TextBlock FontSize="12" Margin="5" TextOptions.TextFormattingMode="Display"> This is a Test. Display text is crisp at small sizes. </TextBlock> </StackPanel> |
3. Buttons With Content
Back to the list
This example presents simply the creation of 4 buttons with content in a stack panel. This is the XAML code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<StackPanel Margin="3"> <Button Margin="3">Text button</Button> <Button Margin="3"> <Image Source="happyface.jpg" Stretch="None" /> </Button> <Button Margin="3"> <StackPanel> <TextBlock Margin="3">Image and text button</TextBlock> <Image Source="happyface.jpg" Stretch="None" /> <TextBlock Margin="3" >Courtesy of the StackPanel</TextBlock> </StackPanel> </Button> <Button Padding="3" Margin="3" HorizontalContentAlignment="Stretch"> <StackPanel> <TextBlock Margin="3">Type something here:</TextBlock> <TextBox Margin="3" HorizontalAlignment="Stretch">Text box in a button</TextBox> </StackPanel> </Button> </StackPanel> |
4. Button with shape
Back to the list
This is more interesting – you receive a shape in the button 🙂 How do you get it? Quite easy actually, just with adding a grid to the button and defining polygon points in it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
<StackPanel Margin="3"> <Button Margin="3">Text button</Button> <Button Margin="3"> <Image Source="happyface.jpg" Stretch="None" /> </Button> <Button Margin="3"> <StackPanel> <TextBlock Margin="3">Image and text button</TextBlock> <Image Source="happyface.jpg" Stretch="None" /> <TextBlock Margin="3" >Courtesy of the StackPanel</TextBlock> </StackPanel> </Button> <Button Padding="3" Margin="3" HorizontalContentAlignment="Stretch"> <StackPanel> <TextBlock Margin="3">Type something here:</TextBlock> <TextBox Margin="3" HorizontalAlignment="Stretch">Text box in a button</TextBox> </StackPanel> </Button> </StackPanel> |
5. Label Text
Back to the list
The idea of this example is to show how to enable the selection of a specific object, using the ALT key and a predefined character. The magic is done in the naming, where you should use the underscore sign “_” before the character you would like to enable. It looks like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<Window x:Class="Controls.LabelTest" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="LabelTest" Height="300" Width="300" > <StackPanel Margin="5"> <Label Target="{Binding ElementName=txtA}">Choose _A</Label> <TextBox Name="txtA"></TextBox> <Label Target="{Binding ElementName=txtB}">Choose _B</Label> <TextBox Name="txtB"></TextBox> </StackPanel> </Window> |
6. Radio Button Groups
Back to the list
In this example, the trick is to name the groups correctly. Although, the groupboxes are the same within the radio buttons, what matters for the selection is the “GroupName” within the StackPanel:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<StackPanel> <GroupBox Margin="5"> <StackPanel> <RadioButton>Group 1</RadioButton> <RadioButton>Group 1</RadioButton> <RadioButton>Group 1</RadioButton> <RadioButton Margin="0,10,0,0" GroupName="Group2">Group 2</RadioButton> </StackPanel> </GroupBox> <GroupBox Margin="5"> <StackPanel> <RadioButton>Group 3</RadioButton> <RadioButton>Group 3</RadioButton> <RadioButton>Group 3</RadioButton> <RadioButton Margin="0,10,0,0" GroupName="Group2">Group 2</RadioButton> </StackPanel> </GroupBox> </StackPanel> |
7. Tooltips
Back to the list
With this example we receive four different types of tooltips – a standard one, a tooltip with picture within, a tooltip which is formatted to go to the left and a tooltip associated to the StackPanel and not to a specific button. Thus we see that if we have two objects with different tooltips (in our case a stack panel and a button within the stack panel), the displayed tooltip is the more detailed one:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
<StackPanel Margin="5" ToolTip="StackPanel tooltip"> <Button ToolTip="This is my tooltip" ToolTipService.InitialShowDelay="5000">I have a tooltip</Button> <Button ToolTipService.InitialShowDelay="0" ToolTipService.BetweenShowDelay="5000"> <Button.ToolTip> <ToolTip Background="#60AA4030" Foreground="White" HasDropShadow="False" > <StackPanel> <TextBlock Margin="3" >Image and text</TextBlock> <Image Source="happyface.jpg" Stretch="None" /> <TextBlock Margin="3" >Image and text</TextBlock> </StackPanel> </ToolTip> </Button.ToolTip> <Button.Content>I have a fancy tooltip</Button.Content> </Button> <Button ToolTip="This is my tooltip" ToolTipService.Placement="Bottom">Placement test</Button> <Button Padding="50">Does Nothing</Button> <TextBox TextWrapping="Wrap" MinLines="2" AutoWordSelection="True"></TextBox> </StackPanel> |
8. PopUp Text
Back to the list
The PopUp Text is simply the solution if you would like to have a clickable tooltip, containing button or a link. The following example contains link to wikipedia:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<Grid Margin="10"> <TextBlock TextWrapping="Wrap">You can use a Popup to provide a link for a specific <Run TextDecorations="Underline" MouseEnter="run_MouseEnter" >term</Run> of interest.</TextBlock> <Popup Name="popLink" StaysOpen="False" Placement="Mouse" MaxWidth="200" PopupAnimation="Slide" AllowsTransparency = "True"> <Border BorderBrush="Beige" BorderThickness="2" Background="White"> <TextBlock Margin="10" TextWrapping="Wrap" > For more information, see <Hyperlink NavigateUri="http://en.wikipedia.org/wiki/Term" Click="lnk_Click">Wikipedia</Hyperlink> </TextBlock> </Border> </Popup> </Grid> |
9. Scrollable TextBox Column
Back to the list
With this example we get a TextBox, which is scrollable. It is made with the creation of a grid, which is bigger than the window itself. Thus we need to scroll. The scrolling itself is achieved through assigning four buttons to void methods in C#. This is the C# code:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
public partial class ScrollableTextBoxColumn : System.Windows.Window { public ScrollableTextBoxColumn() { InitializeComponent(); } private void LineUp(object sender, RoutedEventArgs e) { scroller.LineUp(); } private void LineDown(object sender, RoutedEventArgs e) { scroller.LineDown(); } private void PageUp(object sender, RoutedEventArgs e) { scroller.PageUp(); } private void PageDown(object sender, RoutedEventArgs e) { scroller.PageDown(); } } |
This is the XAML code, for the creation of the application:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
<DockPanel> <Border DockPanel.Dock="Top" BorderBrush="SteelBlue" BorderThickness="2"> <StackPanel Margin="5" Orientation="Horizontal"> <Button Padding="3" Click="LineUp">Line Up</Button> <Button Padding="3" Click="LineDown">Line Down</Button> <Button Padding="3" Click="PageUp">Page Up</Button> <Button Padding="3" Click="PageDown">Page Down</Button> </StackPanel> </Border> <ScrollViewer Name="scroller"> <Grid Margin="0,10,0,0" Focusable="False"> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition Width="Auto"></ColumnDefinition> <ColumnDefinition Width="*" MinWidth="50" MaxWidth="800"></ColumnDefinition> <ColumnDefinition Width="Auto"></ColumnDefinition> </Grid.ColumnDefinitions> <Label Grid.Row="0" Grid.Column="0" Margin="3" VerticalAlignment="Center">Home:</Label> <TextBox Grid.Row="0" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="0" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="1" Grid.Column="0" Margin="3" VerticalAlignment="Center">Network:</Label> <TextBox Grid.Row="1" Grid.Column="1" Margin="3.4,0,3.2,6" Height="Auto" VerticalAlignment="Bottom"></TextBox> <Button Grid.Row="1" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="2" Grid.Column="0" Margin="3" VerticalAlignment="Center">Web:</Label> <TextBox Grid.Row="2" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="2" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="3" Grid.Column="0" Margin="3" VerticalAlignment="Center">Secondary:</Label> <TextBox Grid.Row="3" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="3" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="4" Grid.Column="0" Margin="3" VerticalAlignment="Center">Home:</Label> <TextBox Grid.Row="4" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="4" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="5" Grid.Column="0" Margin="3" VerticalAlignment="Center">Network:</Label> <TextBox Grid.Row="5" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="5" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="6" Grid.Column="0" Margin="3" VerticalAlignment="Center">Web:</Label> <TextBox Grid.Row="6" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="6" Grid.Column="2" Margin="3" Padding="2">Browse</Button> <Label Grid.Row="7" Grid.Column="0" Margin="3" VerticalAlignment="Center">Secondary:</Label> <TextBox Grid.Row="7" Grid.Column="1" Margin="3" Height="Auto" VerticalAlignment="Center"></TextBox> <Button Grid.Row="7" Grid.Column="2" Margin="3" Padding="2">Browse</Button> </Grid> </ScrollViewer> </DockPanel> |
10. Logical Scrolling
Back to the list
Here the idea is, that if you click on a button, which is half seen at the window, the scrolling works automatically and makes it completely visible. As you can imagine this feature should not be difficult for achieving, thus it is just a boolean property of “Scroll Viewer” – “CanContentScroll”:
1 2 3 4 5 6 7 8 |
<ScrollViewer CanContentScroll="True"> <StackPanel > <Button Height="100">1</Button> <Button Height="100">2</Button> <Button Height="100">3</Button> <Button Height="100">4</Button> </StackPanel> </ScrollViewer> |
11. Graphical Tab Titles
Back to the list
The TabItem in XAML is a content element. As such it may contain anything a content element wants 🙂 In this example, our TabItem contains a picture:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<TabControl Margin="5"> <TabItem> <TabItem.Header> <StackPanel> <TextBlock Margin="3" >Image and Text Tab Title</TextBlock> <Image Source="happyface.jpg" Stretch="None" /> </StackPanel> </TabItem.Header> <StackPanel Margin="3"> <CheckBox Margin="3">Setting One</CheckBox> <CheckBox Margin="3">Setting Two</CheckBox> <CheckBox Margin="3">Setting Three</CheckBox> </StackPanel> </TabItem> <TabItem Header="Tab Two"></TabItem> </TabControl> |
12. Expandable Content
Back to the list
Simply an expander in a stack panel. Three expanders are present in the example. The first one contains a button, the second one text. The third one is left expanded:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<StackPanel> <Expander Margin="5" Padding="5" Header="Region One" BorderThickness="1" BorderBrush="Black"> <Button Padding="3">Hidden Button One</Button> </Expander> <Expander Margin="5" Padding="5" Header="Region Two" BorderThickness="1" BorderBrush="Black"> <TextBlock TextWrapping="Wrap"> Tralala </TextBlock> </Expander> <Expander Margin="5" Padding="5" Header="Region Three" IsExpanded="True" BorderThickness="1" BorderBrush="Black"> <Button Padding="3">Hidden Button Two</Button> </Expander> </StackPanel> |
13. Multidirectional Expanders
Back to the list
Here we have quite the same example as before, with the difference that there is a property of the expander, named “ExpandDirection”. It can be “Up”, “Left” or “Right”. When it is not set, it is down:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
<Grid> <Grid.RowDefinitions> <RowDefinition Height="Auto"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Expander Margin="5" Padding="5" Header="Region One" BorderThickness="1" BorderBrush="Black"> <TextBlock TextWrapping="Wrap"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien. </TextBlock> </Expander> <Expander Grid.Column="1" Margin="5" Padding="5" Header="Region Two" ExpandDirection="Right" BorderThickness="1" BorderBrush="Black"> <TextBlock TextWrapping="Wrap"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien. </TextBlock> </Expander> <Expander Grid.Row="1" Margin="5" Padding="5" Header="Region Three" ExpandDirection="Up" BorderThickness="1" BorderBrush="Black"> <TextBlock TextWrapping="Wrap"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien. </TextBlock> </Expander> <Expander Grid.Row="1" Grid.Column="1" Margin="5" Padding="5" Header="Region Three" ExpandDirection="Left" BorderThickness="1" BorderBrush="Black"> <TextBlock TextWrapping="Wrap"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien. </TextBlock> </Expander> </Grid> |
14. ExpandableScrollable Content
Back to the list
We simply have a scroll viewer in the expander. Cool:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<StackPanel> <Expander Margin="5" Padding="5" Header="Region One"> </Expander> <Expander Margin="5" Padding="5" Header="Region Two" > <ScrollViewer Height="50" > <TextBlock TextWrapping="Wrap"> Lorem ipsum dolor sit amet, consectetuer adipiscing elit. Nam mi sapien, viverra et, lacinia varius, ullamcorper sed, sapien. Proin rutrum arcu vitae tellus. Vestibulum ante ipsum primis in faucibus orci luctus et ultrices posuere cubilia Curae; Pellentesque libero dui, eleifend faucibus, auctor at, aliquet a, nulla. Nunc eros. Phasellus mauris nisi, eleifend nec, adipiscing nec, luctus nec, lacus. Aliquam justo metus, vestibulum non, accumsan id, hendrerit at, nibh. Praesent accumsan urna quis tortor. Proin erat libero, facilisis nec, rhoncus ut, malesuada ut, ipsum. Donec id nibh. </TextBlock> </ScrollViewer> </Expander> <Expander Margin="5" Padding="5" Header="Region Three" IsExpanded="True"> <Button Padding="3">Hidden Button Two</Button> </Expander> </StackPanel> |
15. TextBoxTest
Back to the list
Here we have something interesting! (with some C# code behind) – we have TextBox and a TextBlock. Once, something in the TextBox is selected, it is displayed in the TextBlock. Nice:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
<Grid Margin="5"> <Grid.RowDefinitions> <RowDefinition Height="2*"></RowDefinition> <RowDefinition Height="*"></RowDefinition> </Grid.RowDefinitions> <TextBox Name="txt" VerticalScrollBarVisibility="Auto" TextWrapping="Wrap" AcceptsReturn="True" SelectionChanged="txt_SelectionChanged" SpellCheck.IsEnabled="True">The Ministry of Truth c... and Miniplenty. </TextBox> <ScrollViewer Foreground="Blue" Grid.Row="1" Margin="0,10,0,5" VerticalScrollBarVisibility="Auto"> <StackPanel> <TextBlock>Current selection: </TextBlock> <TextBlock Name="txtSelection" TextWrapping="Wrap"></TextBlock> </StackPanel> </ScrollViewer> </Grid> |
How do we achieve it? With creation a C# void method “private void txt_SelectionChanged”. Four lines in the method do the magic:
1 2 3 4 5 6 7 |
private void txt_SelectionChanged(object sender, RoutedEventArgs e) { if (txtSelection == null) return; txtSelection.Text = String.Format( "Selection from {0} to {1} is \"{2}\"", txt.SelectionStart, txt.SelectionLength, txt.SelectedText); } |
16. Custom Spell Checker
Back to the list
The custom spell checker is an option for a spell check, based on a predefined list of words. In the example, the list of words is a simple text file with a “*.lex” extension. In the example we have a text box in which some text is entered. Then through “<SpellCheck.CustomDictionaries><sys:Uri>” we give the path to our *.lex file, containing the words, which are included in the spell check. The code looks like this:
1 2 3 4 5 6 7 8 |
<Grid Margin="5"> <TextBox SpellCheck.IsEnabled="True" TextWrapping="Wrap" Text="Now the spell checker recognizes acantholysis and offers the right correction for acantholysi"> <SpellCheck.CustomDictionaries> <sys:Uri>pack://application:,,,/Controls;component/CustomWords.lex</sys:Uri> </SpellCheck.CustomDictionaries> </TextBox> </Grid> |
17. Image List
Back to the list
Here we have a List Box, containing 3 stack panels. In each stack panel we have image and label. Once a selection is changed, the method “lst_SelectionChanged” is activated. In order to ease the example, the method is empty. It is simple and it looks OK:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
<ListBox Margin="5" SelectionMode="Multiple" Name="lst" SelectionChanged="lst_SelectionChanged"> <StackPanel Orientation="Horizontal"> <Image Source="happyface.jpg" Width="30" Height="30"></Image> <Label VerticalContentAlignment="Center">A happy face</Label> </StackPanel> <StackPanel Orientation="Horizontal"> <Image Source="redx.jpg" Width="30" Height="30"></Image> <Label VerticalContentAlignment="Center">A warning sign</Label> </StackPanel> <StackPanel Orientation="Horizontal"> <Image Source="happyface.jpg" Width="30" Height="30"></Image> <Label VerticalContentAlignment="Center">A happy face</Label> </StackPanel> </ListBox> |
18. CheckBox List
Back to the list
Here we have a a listbox and a stack panel in a grid. What does this application do? Simply displays information about the performed selections in a text block. Two methods help it to do this. The method “lst_SelectionChanged”, which is activated upon a change of the listboxes and a “cmd_CheckAllItems”, which is activated by a button:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 |
private void lst_SelectionChanged(object sender, RoutedEventArgs e) { // Select when checkbox portion is clicked (optional). if (e.OriginalSource is CheckBox) { lst.SelectedItem = e.OriginalSource; } if (lst.SelectedItem == null) return; txtSelection.Text = String.Format( "You chose item at position {0}.\r\nChecked state is {1}.", lst.SelectedIndex, ((CheckBox)lst.SelectedItem).IsChecked); } private void cmd_CheckAllItems(object sender, RoutedEventArgs e) { StringBuilder sb = new StringBuilder(); foreach (CheckBox item in lst.Items) { if (item.IsChecked == true) { sb.Append( item.Content + " is checked."); sb.Append("\r\n"); } } txtSelection.Text = sb.ToString(); } |
The XAML file is a neat one:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
<Grid Margin="10"> <Grid.RowDefinitions> <RowDefinition Height="*"></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <ListBox Name="lst" SelectionChanged="lst_SelectionChanged" CheckBox.Click="lst_SelectionChanged" > <CheckBox Margin="3">Option 1</CheckBox> <CheckBox Margin="3">Option 2</CheckBox> <CheckBox Margin="3">Option 3</CheckBox> </ListBox> <StackPanel Grid.Row="1" Margin="0,10,0,0"> <TextBlock>Current selection: </TextBlock> <TextBlock Name="txtSelection" TextWrapping="Wrap"></TextBlock> <Button Margin="0,10,0,0" Click="cmd_CheckAllItems">Examine All Items</Button> </StackPanel> </Grid> |
19. Combo Box Text
Back to the list
Do you think you can put a picture on a drop-down menu? Yes? Well, in this case you are probably right. The book “Pro WPF 4.5. in C#” gives you a good way to do it:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
<StackPanel> <ComboBox Margin="5" > <StackPanel Orientation="Horizontal"> <Image Source="happyface.jpg" Width="30" Height="30"></Image> <Label VerticalContentAlignment="Center">A happy face</Label> </StackPanel> <StackPanel Orientation="Horizontal"> <Image Source="redx.jpg" Width="30" Height="30"></Image> <Label VerticalContentAlignment="Center">A warning sign</Label> </StackPanel> <StackPanel Orientation="Horizontal"> <Image Source="happyface.jpg" Width="30" Height="30"></Image> <Label VerticalContentAlignment="Center">A happy face</Label> </StackPanel> </ComboBox> </StackPanel> |
20. Slider Test
Back to the list
Sometimes we need a slider in WPF. XAML gives us a good opportunity to create one, using the “<Slider>”. It is easy and understandable. In the below example, we set Margin, TickFrequency, TickPlacement, Maximum, Delay and Interval properties:
1 2 3 4 5 6 7 8 9 10 11 12 |
<StackPanel> <TextBlock Margin="10" TextWrapping="Wrap"> A Delay of 0 and Interval of 1 make this a fast slider. Try clicking on either side of the thumb and holding down the mouse button.</TextBlock> <Slider Margin="10" TickFrequency="1" TickPlacement="TopLeft" Maximum="10" Delay="0" Interval="1" > </Slider> </StackPanel> |
21. Sliders Compared
Back to the list
Here the author gives us four slider examples. Normal slider, slider with tick marks (these are the marks below the line of the slider), slider with irregular tick marks and slider with selection range. The slider with selection range is a slider, where you simply define the range, which should be colored in blue (the default color). This is how it looks like:
1 2 3 4 5 6 7 8 9 10 11 12 13 |
<Grid> <StackPanel Margin="10"> <TextBlock Margin="0,0,0,5">Normal Slider (Max=100, Val=10)</TextBlock> <Slider Maximum="100" Value="10"></Slider> <TextBlock Margin="0,15,0,5">Slider with Tick Marks (TickFrequency=10, TickPlacement=BottomRight)</TextBlock> <Slider Maximum="100" Value="10" TickFrequency="10" TickPlacement="BottomRight"></Slider> <TextBlock Margin="0,15,0,5">Slider with Irregular Tick Marks (Ticks=0,5,10,15,25,50,100)</TextBlock> <Slider Maximum="100" Value="10" Ticks="0,5,10,15,25,50,100" TickPlacement="BottomRight"></Slider> <TextBlock Margin="0,15,0,5" TextWrapping="Wrap">Slider with a Selection Range (IsSelectionRangeEnabled=True, SelectionStart=25, SelectionEnd=75)</TextBlock> <Slider Maximum="100" Value="10" TickFrequency="10" TickPlacement="BottomRight" IsSelectionRangeEnabled="True" SelectionStart="25" SelectionEnd="75" ></Slider> </StackPanel> </Grid> |
22. Interdeterminate Progress Bar
Back to the list
Just a progress bar, which keeps on rolling:
1 2 3 |
<StackPanel Margin="5"> <ProgressBar Height="10" IsIndeterminate="True"></ProgressBar> </StackPanel> |
23. Date Controls
Back to the list
Date controls – having <DatePicker> and <Calendar> in XAML makes really a good job for us. With a few lines we get beautiful result:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 |
<Grid Background="White" Margin="3"> <Grid.ColumnDefinitions> <ColumnDefinition></ColumnDefinition> <ColumnDefinition></ColumnDefinition> </Grid.ColumnDefinitions> <Grid.RowDefinitions> <RowDefinition></RowDefinition> <RowDefinition Height="Auto"></RowDefinition> </Grid.RowDefinitions> <StackPanel> <Calendar Margin="3" SelectionMode="MultipleRange" SelectedDatesChanged="Calendar_SelectedDatesChanged" ></Calendar> <Calendar Margin="3" DisplayMode="Year" SelectedDatesChanged="Calendar_SelectedDatesChanged" ></Calendar> </StackPanel> <StackPanel Grid.Column="1"> <DatePicker Margin="3" DateValidationError="DatePicker_DateValidationError" ></DatePicker> <DatePicker Margin="3" SelectedDateFormat="Long" DateValidationError="DatePicker_DateValidationError" ></DatePicker> </StackPanel> <TextBlock Grid.Row="1" Grid.ColumnSpan="2" x:Name="lblError" Foreground="Red" TextWrapping="Wrap"></TextBlock> </Grid> |
However, in order to make it more beautiful, the author of the book has decided to put some C# coding in the example. Thus, it is not allowed to pick a date from the weekends and if you select some imaginary date from the date pickers on the right you get an error as well. The errors are displayed in a text block, which is named “lblError”. Here is the C# code with the two methods, helping us to achieve this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
private void DatePicker_DateValidationError(object sender, DatePickerDateValidationErrorEventArgs e) { lblError.Text = "'" + e.Text + "' is not a valid value because " + e.Exception.Message; } private void Calendar_SelectedDatesChanged(object sender, SelectionChangedEventArgs e) { // Check all the newly added items. foreach (DateTime selectedDate in e.AddedItems) { if ((selectedDate.DayOfWeek == DayOfWeek.Saturday) || (selectedDate.DayOfWeek == DayOfWeek.Sunday)) { lblError.Text = "Weekends are not allowed"; ((Calendar)sender).SelectedDates.Remove(selectedDate); } } } |
To summarize, chapter 6 of the book is really a must-read chapter for everyone dealing with C# and XAML. It simply gives you good practices for the creation of controls.