Mindscape Mindblog

Archive for the ‘WPF Elements’ Category

Nightly news, 20 August 2010

It’s been an enterprisy kind of a week: started out with a meeting, then our Dauntless Leaders went to an industry seminar and to cap it all off we’ve entered the SharePoint market. We’ve even got a pretty thin change log for this week. It doesn’t get much enterprisier than that.

LightSpeed

  • Improved DTO guidance sample
  • Added batch insert support for Amazon SimpleDB
  • Fixed a couple of cases that could cause “unresolved identifier” alias errors in generated SQL

WPF Elements

  • Added controls for single-day display — see the multiple schedule sample here
  • Fixed an issue where TimePicker wasn’t showing the current value

WPF Diagramming

  • Fixed an issue where printing wasn’t respecting node elements being hidden

As always, these fixes and enhancements are in the current nightlies — free and trial editions from the downloads page, retail editions from the store.

WPF Elements: How to build a multi-scheduler

tag icon Tagged as WPF, WPF Elements

One of the controls you’ll find in Mindscape WPF Elements is the Scheduler which allows users to create, edit and manage their appointments. A single scheduler control can only display appointments for a single person. In this blog post we look at how to use some of the new parts that we provide to build up your own scheduler that can display schedules for different people simultaneously. This will be similar to what Microsoft Outlook 2010 provides as seen here:

Outlook 2010

By downloading the latest nightly build of WPF Elements, you’ll see there are some new controls at your disposal. The TimeOfDayBar is used to display each hour of the day in a vertical arrangement. The DaySchedule control displays appointments for a single day, and the DayScheduleSummary control displays appointments that are 24 hours or longer. The DaySchedule and DayScheduleSummary have their own properties for setting the current date and the schedule that they display. Each of these controls can be used by themselves allowing you to build them up in what ever arrangement you like. For this project, we want to display 3 different schedules side by side. Each schedule will be made up of the following parts: A header that displays a title and the current day, a DayScheduleSummary control and a DaySchedule control.

Step 1

The first thing that we need to do is build our own control that bundles these parts together. This will make them easier to use and style. I’ve called this the DayViewControl and it contains the following dependency properties:

  • Schedule: used to set the schedule that both the DaySchedule and DayScheduleSummary controls display.
  • Date: used to specify which day is being displayed.
  • Title: used to give each schedule its own name.
  • VerticalOffset: used to synchronize all the scroll bars together.

Step 2

Next we create a style for this custom control which colors and arranges all the parts however we like. This style also includes the DaySchedule and DayScheduleSummary controls and sets some of their properties as seen below.

<ms:DayScheduleSummary Schedule="{Binding Schedule, RelativeSource={RelativeSource TemplatedParent}}" Grid.Row="1"
                       Date="{Binding Date, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                       Name="PART_DayScheduleSummary" />
<ms:DaySchedule Grid.Row="2" Schedule="{Binding Schedule, RelativeSource={RelativeSource TemplatedParent}}"
                Date="{Binding Date, RelativeSource={RelativeSource TemplatedParent}, Mode=TwoWay}"
                VerticalOffset="{Binding VerticalOffset, Mode=TwoWay, RelativeSource={RelativeSource TemplatedParent}}"
                Name="PART_DaySchedule" />

Here you can see we are binding the schedule and date properties of both these controls to the schedule and date of the DayViewControl. The binding for the date property is a two way binding because some of the features of the DaySchedule control can change the date internally. We are also binding the VerticalOffset property of the DaySchedule which aids in synchronizing the scroll bars across all the schedules.

Step 3

Within the application window, we can now place 3 instances of our DayViewControl side by side. To the left of these, we can place a TimeOfDayBar, and to the right will be a scroll bar. This arrangement can be seen in the following xaml:

<ms:TimeOfDayBar Margin="0,125,0,4" VerticalOffset="{Binding VerticalOffset, Mode=TwoWay, ElementName=Calendar1}" Name="TimeOfDayBar" />
<local:DayViewControl Style="{StaticResource DayViewControlStyle}" x:Name="Calendar1" Grid.Column="1" BorderBrush="#9CBF8B"
                      Background="#C1D8B7" Margin="0,0,6,0" Title="Ratchet" DateChanged="Calendar1_DateChanged" GotFocus="Calendar_GotFocus" />
<local:DayViewControl Style="{StaticResource DayViewControlStyle}" x:Name="Calendar2" Grid.Column="2" Margin="3,0,3,0" BorderBrush="#D195AA" Background="#E1BCC9"
                      Date="{Binding Date, ElementName=Calendar1, Mode=TwoWay}" VerticalOffset="{Binding VerticalOffset, Mode=TwoWay, ElementName=Calendar1}"
                      Title="Clank" GotFocus="Calendar_GotFocus" />
<local:DayViewControl Style="{StaticResource DayViewControlStyle}" x:Name="Calendar3" Grid.Column="3" BorderBrush="#8C8CD7" Margin="6,0,0,0" Background="#AFAFE4"
                      Date="{Binding Date, ElementName=Calendar1, Mode=TwoWay}" VerticalOffset="{Binding VerticalOffset, Mode=TwoWay, ElementName=Calendar1}"
                      Title="Dr. Nefarious" GotFocus="Calendar_GotFocus" />
<ScrollBar Maximum="{Binding ActualHeight, Converter={StaticResource ScrollBarMaximum}, RelativeSource={RelativeSource Self}}"
           SmallChange="30" LargeChange="30" ViewportSize="{Binding ActualHeight, RelativeSource={RelativeSource Self}}"
           Grid.Column="4" Value="{Binding VerticalOffset, Mode=TwoWay, ElementName=Calendar1}" Orientation="Vertical" Margin="0,126,0,0" />

Here you will notice that we are binding all the dates and vertical offsets of the DayViewControls together. The verticalOffset of the TimeOfDayBar and the ScrollBar are also bound together so that they all move as one.

And thats it

Overall, this produces the following result:

Ratchet and Clank Schedule

The source code for the full project can be downloaded here. Make sure you install the latest nightly build and include a reference to your copy of WPF Elements. The project also demonstrates how to use the SchedulerNavigationBar to change the current day, and how to only allow one appointment to be selected across all the DayViewControls. Using these new controls you can create all sort of scheduler arrangements, or generalize this sample to display a variable number of schedules.

If you need advice on building your own scheduler using WPF Elements, then leave a comment on this blog, or let us know in the forum.

WPF Elements: Custom DualSlider tick mark style

tag icon Tagged as WPF, WPF Elements

The Mindscape WPF DualSlider has various features related to displaying tick marks similar to that provided by the standard WPF Slider control. The TickSpacing property allows you to set the logical distance between each of the tick marks. A pair of boolean properties called ShowTopLeftTickMarks and ShowBottomRightTickMarks specifies whether the tick marks are displayed on the top, bottom, or both edges of the slider track. Additionally, you can snap the slider thumbs to the tick marks by setting the SnapToTickMarks property to true. In this blog post we look at how to make a custom DualSlider style that has different sized tick marks based on their positions.

After setting the various properties mentioned above, the DualSlider controls generates a ReadOnlyCollection of doubles that can be acquired using the TickPositions property. This is a collection of physical positions that can be used in a style to place the tick marks. The numbers in the collection represent the distance from the left side of the slider track to each individual tick mark as illustrated below.

Tick mark positions

To style the tick marks, we can use the tick positions collection as the items source of an ItemsControl. Then we template each number to be a Border that only renders as a line on its right hand edge. The width of this border is a binding to the number itself which places the ‘tick mark’ in the correct place. Now, in order for us to render each tick mark with a different height, we start by making a class to represent an individual tick mark. Tick marks will need to know their position as well as their size which gives us the following class.

public class TickMark
{
  public double Position { get; set; }
  public double Size { get; set; }
}

Instead of filling an ItemsControl with a collection of positions, we now want to give it a collection of TickMark objects. This is easily achieved using a custom converter that will take the collection of positions and create instances of our TickMark objects. Within this converter, we will iterate through each of the positions and create a TickMark using the respective position. The size of each TickMark will be based on the index of the current position. Part of this converter class can be seen below.

// Size properties:
public int Size0 { get; set; }
    ...
public int Size9 { get; set; }
 
// Convert method:
public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
  ReadOnlyCollection<double> positions = (ReadOnlyCollection<double>)value;
  IList<TickMark> tickMarks = new List<TickMark>();
  int count = 0;
  foreach (double d in positions)
  {
    double size = GetSize(count % 10);
    TickMark tickMark = new TickMark() { Position = d, Size = size };
    tickMarks.Add(tickMark);
    count++;
  }
  return tickMarks;
}
 
// Returns the size of a tick mark for the given modular interval.
private int GetSize(int remainder)
{
  switch (remainder)
  {
    case 0:
      return Size0;
 
    ...
 
    case 9:
      return Size9;
  }
  return 0;
}

In the Convert method we use the ‘count’ variable to keep track of what index we are at within the loop. We perform the modular operation on this variable and use the result to select the size of the TickMark. The converter has 10 properties that will let us set the size to be given to each TickMark based on their modular index. This converter can be used in xaml as follows.

<local:TickMarkListConverter x:Key="TickMarkListConverter" Size0="9" Size5="6" />
 
<DataTemplate x:Key="HorizontalTickTemplate">
    <Border BorderThickness="0,0,1,0" BorderBrush="Black" Height="{Binding Size}" MinWidth="1"
               Width="{Binding Position}" HorizontalAlignment="Left" VerticalAlignment="Top" />
</DataTemplate>
 
<Style x:Key="HorizontalTickListStyle" TargetType="ItemsControl">
  <Setter Property="ItemTemplate" Value="{StaticResource HorizontalTickTemplate}" />
  <Setter Property="ItemsPanel">
    <Setter.Value>
      <ItemsPanelTemplate>
        <Grid />
      </ItemsPanelTemplate>
    </Setter.Value>
  </Setter>
</Style>

When creating a DualSlider template, we can use an ItemsControl and set its ItemsSource to be a binding to the DualSlider.TickPositions property using the converter. The HorizontalTickTemplate as seen above uses the TickMark.Size property to set its height. Combining this with custom slider thumb and track styles can achieve results such as this:

Custom DualSlider style

Using this technique you can create all sorts of DualSlider styles involving tick marks with varying sizes or colors based on the requirements of your applications. A sample including all the source code for creating a custom DualSlider style in this way can be downloaded here. Let us know if you need help with styling any of the controls in WPF Elements by leaving a comment on this blog post or letting us know in the forum.

Click here to download the trial of WPF Elements.

Nightly news, 13 August 2010

We’ve had another busy shipping week this week, so it’s fairly quiet on the nightly builds front. Here’s what’s new in the latest builds.

LightSpeed

  • Added EntityFactory.UpdateEntityState to the Testing namespace.
  • Fixed an issue when performing multiple joins to the same entity.
  • Fixed an issue where ForeignKeyFieldAttribute was not respected in eager loads.
  • Improved support for keyboard-only editing in the designer. We’ll write more about this in another post.

WPF Elements

  • Added disabled control visuals to themes.

All of these are available in the current nightly builds — free editions from the Downloads page, retail editions from the store.

WPF Elements: RichTextToolBar Control

tag icon Tagged as WPF Elements

A few days ago we released WPF Elements 3.0 which has been packed with some great new controls. One of these controls is the RichTextToolBar which provides a user interface to the standard WPF RichTextBox.

RichTextToolBar

This currently supports the following text formatting: bold, italic, underline, foreground and background color, font family and font size. Text alignment for individual paragraphs can be changed using toggle buttons for left, center, right and justify alignment. And finally, cut, copy, paste, undo and redo commands are also included. Another thing to point out is that the bold command is not limited to a single font weight. Any font weight provided by WPF can be used by the RichTextToolBar. Using the RichTextToolBar in your applications is achieved with only a couple of lines of xaml:

<ms:RichTextToolBar RichTextBox="{Binding ElementName=RichTextBox}" FontSelectorDisplayMode="Plain" />
<RichTextBox Name="RichTextBox">

Simply put this code into a StackPanel or a Grid and your ready to go. The FontSelectorDisplayMode property that you can see on the RichTextBoolBar is used to specify whether or not the items in the font family combo box should be templated using their respective fonts.

Styling the RichTextToolBar

The RichTextToolBar control does not make any assumptions about what controls are being used for each command. It works purely by using WPF commands and data binding which allows for flexible control styling. Here are some ideas that you may consider if you want to make your own RichTextToolBar style. The foreground and background color pickers need not be the same. They could display different color palettes, or be two completely different controls. You could use any one of our color picker controls, or implement a specialized one for you application. You could use a split button control for the bold command where the drop down part contains a list of alternate font weights. The entire control could even by styled to look like the microsoft office ribbon control.

The RichTextToolBar has various properties to get and set the current state of the selected text in respect to a particular text format. This is useful for setting up two way bindings between properties such as the CurrentFontSize of the RichTextToolBar and the SelectedValue of the font-size combo box. Some properties such as CurrentFontFamily will be set to DependencyProperty.UnsetValue when the selection contains multiple sections of text with different font families. For text formatting that will be controlled by a button, you can use commands instead of bindings. Some of these commands, as seen below, are provided by WPF and so will be familiar to use.

  • ApplicationCommands.Cut
  • ApplicationCommands.Copy
  • ApplicationCommands.Paste
  • ApplicationCommands.Undo
  • ApplicationCommands.Redo

Other commands can be found in the RichTextCommands class and can be used for setting the text alignment, font weight, font style and text decorations. These commands are used along with a command parameter which specifies what to be applied to the selected text.

As usual, WPF Elements comes with 5 themes that can be applied to this control which you can see below. These themes use controls that will be familiar to users, and also include tool tips which mention the various keyboard shortcuts.

RichTextToolBar Styles

If you need help with making a custom style for this control, or if there are any features that you would like to see in the RichTextToolBar, then let us know in our forum and we’ll help you out.

You can grab a free trial of WPF Elements by clicking here!