Logo
programming4us
programming4us
programming4us
programming4us
Home
programming4us
XP
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server
programming4us
Windows Phone
 
Windows Phone

The App Bar and Controls - RangeBase and Slider

- Free product key for windows 10
- Free Product Key for Microsoft office 365
- Malwarebytes Premium 3.7.1 Serial Keys (LifeTime) 2019
3/16/2011 10:42:44 PM
You’ve probably already grasped that scrollbars and sliders are not required as much on multi-touch screens as they are in mouse-based environments.

Still, scrollbars and sliders are sometimes useful for jobs that allow the user to select from a continuous range of values. These controls are found in this little corner of the class hierarchy:

Control (abstract)
RangeBase (abstract)
ProgressBar
ScrollBar (sealed)
Slider

The RangeBase class defines Minimum, Maximum, SmallChange, and LargeChange properties to define the parameters of scrolling, plus a Value property for the user’s selection and a ValueChanged event that signals when Value has changed. (Notice that ProgressBar also derives from RangeBase, but the Value property is always controlled programmatically rather than being set by the user.)

I’m going to focus on the Slider here because the version in Windows Phone 7 seems a little more tailored to the phone than the ScrollBar. The goal is to use three Slider controls to create a program called ColorScroll that looks like this:



You scroll the red, green, and blue Slider controls to define a composite color. To make it more interesting, when the phone is turned sideways, I want the visuals to re-orient themselves slightly so it looks like this:



The easiest way to architect such a display is with nested grids. One grid has three rows and three columns containing the three Slider controls and six TextBlock elements. That Grid is in another Grid with just two cells. The other cell holds a Rectangle element whose Fill property is set to a SolidColorBrush based on the color selected from the sliders.

That larger Grid with the two cells is the familiar Grid named ContentPanel. Whether those two cells are two rows or two columns is determined by the code-behind file based on the current Orientation property.

The XAML file contains a Resources collection with Style definitions for both TextBlock and Slider:

Example 1. Silverlight Project: ColorScroll File: MainPage.xaml (excerpt)
<phone:PhoneApplicationPage.Resources>
<Style x:Key="textStyle" TargetType="TextBlock">
<Setter Property="HorizontalAlignment" Value="Center" />
</Style>

<Style x:Key="sliderStyle" TargetType="Slider">
<Setter Property="Minimum" Value="0" />
<Setter Property="Maximum" Value="255" />
<Setter Property="Orientation" Value="Vertical" />
</Style>
</phone:PhoneApplicationPage.Resources>

A Style with just one Setter seems a bit ostentatious, but it’s nice to have if you ever want to add another Setter for the Margin or FontSize. The default range of a Slider is 0 to 10; I’ve changed that to make the range appropriate for a one-byte value.

ScrollBar and Slider have their own Orientation properties, entirely unrelated to the Orientation property of PhoneApplicationPage but somewhat related to the Orientation property of StackPanel because they both share the same Orientation enumeration with values of Horizontal and Vertical.

The default Orientation of a Slider is Horizontal. (For a ScrollBar it’s Vertical, a difference I’ve never quite understood.)

By default, the top of a vertical Slider is associated with the Maximum value. That’s OK for this program but you can change it by setting the IsDirectionReversed property to true.

Here’s the whole content panel:

Example 2. Silverlight Project: ColorScroll File: MainPage.xaml (excerpt)
<Grid x:Name="<Grid x:Name="ContentPanel" Grid.Row="1" Margin="12,0,12,0">
<Grid.RowDefinitions>
<RowDefinition Height="*" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>

<Rectangle Name="rect"
Grid.Row="0"
Grid.Column="0" />

<Grid Name="controlGrid"
Grid.Row="1"
Grid.Column="0">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>

<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>

<!-- Red column -->
<TextBlock Grid.Column="0"
Grid.Row="0"
Text="Red"
Foreground="Red"
Style="{StaticResource textStyle}" />

<Slider Name="redSlider"
Grid.Column="0"
Grid.Row="1"
Foreground="Red"
Style="{StaticResource sliderStyle}"
ValueChanged="OnSliderValueChanged" />

<TextBlock Name="redText"
Grid.Column="0"
Grid.Row="2"
Text="0"
Foreground="Red"
Style="{StaticResource textStyle}" />

<!-- Green column -->
<TextBlock Grid.Column="1"
Grid.Row="0"
Text="Green"
Foreground="Green"
Style="{StaticResource textStyle}" />

<Slider Name="greenSlider"
Grid.Column="1"
Grid.Row="1"
Foreground="Green"
Style="{StaticResource sliderStyle}"
ValueChanged="OnSliderValueChanged" />

<TextBlock Name="greenText"
Grid.Column="1"
Grid.Row="2"
Text="0"
Foreground="Green"
Style="{StaticResource textStyle}" />

<!-- Blue column -->
<TextBlock Grid.Column="2"
Grid.Row="0"
Text="Blue"
Foreground="Blue"
Style="{StaticResource textStyle}" />

<Slider Name="blueSlider"
Grid.Column="2"
Grid.Row="1"
Foreground="Blue"
Style="{StaticResource sliderStyle}"
ValueChanged="OnSliderValueChanged" />

<TextBlock Name="blueText"
Grid.Column="2"
Grid.Row="2"
Text="0"
Foreground="Blue"
Style="{StaticResource textStyle}" />
</Grid>
</Grid>

All the Slider controls have their ValueChanged events set to the same handler. This handler really takes an easy way out by not bothering to determine which Slider actually raised the event:

Example 3. Silverlight Project: ColorScroll File: MainPage.xaml.cs (excerpt)
void OnSliderValueChanged(object sender, RoutedPropertyChangedEventArgs<double> args)
{
Color clr = Color.FromArgb(255, (byte)redSlider.Value,
(byte)greenSlider.Value,
(byte)blueSlider.Value);

rect.Fill = new SolidColorBrush(clr);

redText.Text = clr.R.ToString("X2");
greenText.Text = clr.G.ToString("X2");
blueText.Text = clr.B.ToString("X2");
}

You may have noticed that the XAML file doesn’t initialize the Value property of any Slider. Here’s why:

As the page is being constructed, various elements and controls are created, event handlers are linked to events, and properties are set. When a new Value property is set to a Slider in the construction of this page, the Slider fires the ValueChanged event. It is extremely likely that the OnSliderValueChanged method in MainPage will be called before the page has been entirely constructed. But OnSliderValueChanged references other elements in the visual tree. If those element do not yet exist, a runtime exception will result.

Want to see it happen? Try setting

<Setter Property="Value" Value="128" />

in the Style definition for the Slider.

Causing an event to be fired while the visual tree is being constructed is a common pitfall. You can either bullet-proof your event handlers by checking for null elements and controls, or you can do what I do in ColorScroll: Properties that trigger events in the page are safely set in the class’s constructor after the call to InitializeComponent when the visual tree has been entirely built:

Example 4. Silverlight Project: ColorScroll File: MainPage.xaml.cs (excerpt)
public MainPage()
{
InitializeComponent();
redSlider.Value = 128;
greenSlider.Value = 128;
blueSlider.Value = 128;
}

To handle orientation changes in the phone, MainPage overrides its OnOrientationChanged method. The event arguments include a property named Orientation of type PageOrientation.

It helps to know that the PageOrientation enumeration values are bit flags with the following values:

None0000–0000
Portrait0000–0001
Landscape0000–0010
PortraitUp0000–0101
PortraitDown0000–1001
LandscapeLeft0001–0010
LandscapeRight0010–0010

You can check for portrait or landscape by performing a bitwise OR operation between the Orientation property and the Portrait or Landscape members, and then checking for a non-zero result. It makes the code just a little simpler:

Example 5. Silverlight Project: ColorScroll File: MainPage.xaml.cs (excerpt)
protected override void OnOrientationChanged(OrientationChangedEventArgs args)
{
ContentPanel.RowDefinitions.Clear();
ContentPanel.ColumnDefinitions.Clear();

// Landscape
if ((args.Orientation & PageOrientation.Landscape) != 0)
{
ColumnDefinition coldef = new ColumnDefinition();
coldef.Width = new GridLength(1, GridUnitType.Star);
ContentPanel.ColumnDefinitions.Add(coldef);

coldef = new ColumnDefinition();
coldef.Width = new GridLength(1, GridUnitType.Star);
ContentPanel.ColumnDefinitions.Add(coldef);

Grid.SetRow(controlGrid, 0);
Grid.SetColumn(controlGrid, 1);
}
// Portrait
else
{
RowDefinition rowdef = new RowDefinition();
rowdef.Height = new GridLength(1, GridUnitType.Star);
ContentPanel.RowDefinitions.Add(rowdef);

rowdef = new RowDefinition();
rowdef.Height = new GridLength(1, GridUnitType.Star);
ContentPanel.RowDefinitions.Add(rowdef);

Grid.SetRow(controlGrid, 1);
Grid.SetColumn(controlGrid, 0);

}
base.OnOrientationChanged(args);
}

The ContentPanel object needs to be switched between two rows for portrait mode and two columns for landscape mode, so it creates the GridDefinition and ColumnDefinition objects for the new orientation. (Alternatively, it could create these collections ahead of time and just switch back and forth. Or it could create a 2-cell by 2-cell Grid in the XAML file and set the unused row or column to a zero height or width.)

The Rectangle element is always in the cell with Grid.Row and Grid.Column settings of zero. But the Grid named controlGrid must have its Grid.Row and Grid.Column attached properties set using the syntax.

Other -----------------
- The App Bar and Controls - Elements and Controls
- The App Bar and Controls - Jot and the ApplicationBar
- The App Bar and Controls - Jot and Touch
- The App Bar and Controls - Jot and Application Settings
- The App Bar and Controls - ApplicationBar Icons
- Issues in Application Architecture - Xna Tombstoning and Settings
- Issues in Application Architecture - Isolated Storage
- Issues in Application Architecture - Page State
- Issues in Application Architecture - Task Switching on the Phone
- Issues in Application Architecture - Retaining Data across Instances
 
 
Top 10
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 2) - Wireframes,Legends
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Finding containers and lists in Visio (part 1) - Swimlanes
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Formatting and sizing lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Adding shapes to lists
- Microsoft Visio 2013 : Adding Structure to Your Diagrams - Sizing containers
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 3) - The Other Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 2) - The Data Properties of a Control
- Microsoft Access 2010 : Control Properties and Why to Use Them (part 1) - The Format Properties of a Control
- Microsoft Access 2010 : Form Properties and Why Should You Use Them - Working with the Properties Window
- Microsoft Visio 2013 : Using the Organization Chart Wizard with new data
 
programming4us
Windows Vista
programming4us
Windows 7
programming4us
Windows Azure
programming4us
Windows Server