CodeZine(コードジン)

特集ページ一覧

ノブ型コントロールで数値を操作できる
Silverlightのカウントダウンタイマーアプリケーションを作る

ComponentOne Studio for SilverlightのC1Knobコントロールを使ったWebページの作成

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加
2011/03/28 14:00

 ComponentOne Studio for SilverlightのC1Knobコントロールは、カセットコンロのノブのような形状をしたコントロールで、ノブを回すことで数値の増減を行うことができます。今回はこのC1Knobコントロールと、.NET FrameworkクラスライブラリのDispatcherTimerクラスを組み合わせ、カウントダウンタイマーを持ったWebページを作成してみました。

はじめに

 Silverlightの特徴の1つは、アニメーションを使って視覚的に操作をすることができる点です。これにより、ユーザーはこれまでにない操作感で、Webページを操作できるようになりました。ComponentOne Studio for SilverlightのC1Knobコントロールは、カセットコンロのノブのような形状をしたコントロールで、ノブを回すことで数値の増減を行うことができます。マウスポインタをドラッグすることでノブを操作することができるため、ユーザーは手でノブを回すのと同じような感覚で、コントロールを操作できます。

 そこで、今回はこのC1Knobコントロールと、.NET FrameworkクラスライブラリのDispatcherTimerクラスを組み合わせ、カウントダウンタイマーを持ったWebページを作成してみました。

ノブをマウスでドラッグして回し、タイマー動作時間を設定する
ノブをマウスでドラッグして回し、タイマー動作時間を設定する
Startボタンを押すと1秒ごとにカウントダウンを始める
Startボタンを押すと1秒ごとにカウントダウンを始める

対象読者

 Visual Basic/Visual C# 2008を使ってプログラムを作ったことのある人。また、SilverlightおよびXAMLに対する基礎的な知識が必要になります。

必要な環境

 Visual Basic 2008、Visual C# 2008、Visual Studio 2008でプログラムが作れる環境。また、Visual Studio 2008 Silverlight Tools 3.0をインストールしていることが必須条件です。なお、本プログラムはWindows Vista上で動作するVisual Studio 2008およびVisual Studio 2008 Silverlight Tools 3.0を使用して作成し、Intenet Explorer 8で動作確認を行っています。

コンポーネントのインストール

 ComponentOne Studio for Silverlightを使用する方は、Visual Studio、Visual Basic、Visual C#の開発環境にComponentOne Studio Enterprise 2010Jをインストールする必要があります。インストーラは、グレープシティのWebページからダウンロードできます。

 製品ページの[申込フォーム]をクリックし、グレープシティのWebサイトへ必要情報を登録すると、添付トライアルライセンスキーファイルとダウンロードサイトを記載したE-Mailが送られてきますので、ここからダウンロードします。制限事項などの詳細については、インストーラに同梱されているリリースノートを参照ください。

ComponentOne Studio for SilverlightのC1Knobコントロールについて

 ComponentOne Studio for SilverlightのC1Knobコントロールは、ユーザーがポインタを回転して数値を選択できるコントロールです。音楽プレイヤーのボリュームつまみなど、ノブを回転させて数値を入力する処理などに最適です。

 「Maximum」「Minimum」プロパティでノブを動かした時の数値の範囲を設定し、「Value」プロパティに現在のノブの位置が格納されます。ノブそのものの動作範囲は、「StartAngle」「SweepAngle」の2つのプロパティで決定します。

 ちょっと分かりづらいのですが、ノブの実際の動作範囲とコントロールが返す値の範囲は別々に設定します。例えば、次のC1Knobコントロールは「0」から「120」までの値の範囲で数値の増減を行いますが、実際にノブが動作するのは12時位置を0度として時計回りに200度の位置を開始位置とし、270度の位置まで動作します。

<c1gauge:C1Knob x:Name="c1kb1" Width="200" Minimum="0" Maximum="120" StartAngle="200" 
                SweepAngle="270" InteractionMode="Drag">
ノブの動きと返してくる数値の範囲
ノブの動きと返してくる数値の範囲

 また、C1Knobコントロール単体では数値目盛りや目盛り線は付いていません。これらは、「C1GaugeLabel」「C1GaugeMark」クラスを使って設定します。目盛り線は、「DataTemplate」を使用してカスタマイズすることができます。

C1Knobコントロールの各要素(※ヘルプファイルから抜粋)
C1Knobコントロールの各要素(※ヘルプファイルから抜粋)

 また、C1Knobコントロールの動作を「InteractionMode」プロパティを使って設定することができます。設定値は「KnobInteractionMode列挙体」のメンバで、次の値を使うことができます。

InteractionModeのプロパティ
説明
Drag ユーザーがドラッグすることでポインタが移動します。
Click ユーザーがノブ内をクリックすることでポインタが移動します。
ClickOrDrag ユーザーがノブ内をクリックするか、ポインタをドラッグすることでポインタが移動します。

 C1Knobコントロールのデフォルトのイベントは「ValueChanged」で、ノブを動かすとこのイベントハンドラが呼び出されます。

Webページの作成

 では、さっそくWebページを作成してみましょう。グリッドは1行2列に設定し、左側のグリッドにC1KnobコントロールとButtonコントロールを、右側のグリッドにTextBlockコントロールを配置します。

 今回のWebページは、ノブを回して0から120までの間の秒数をセットすると、TextBlockにその値が表示されます。そして、「Start」ボタンを押すとタイマーが作動し、セットした秒数を1秒ごとにカウントダウンしていきます。ノブの設定値が「0」になるとタイマーが停止します。また、「Stop」ボタンを押してもタイマーが停止します。

 カウントダウン用タイマーは、「System.Windows.Threading」名前空間にある「DispatcherTimer」クラスを利用します。このクラスのインスタンスは、コードから作成しバックグラウンドプロセスとして作動するので、Webページには表示されません。

コントロールのレイアウト(※GridのShowGridLinesプロパティを"True"にしてグリッド線を表示しています)
コントロールのレイアウト(※GridのShowGridLinesプロパティを"True"にしてグリッド線を表示しています)

Silverlightプロジェクトの作成

 まずは、Silverlightプロジェクトの作成からです。

 Visual Studio 2008 Silverlight Tools 3.0をインストールし、Visual Studioで新しいプロジェクトを作成すると、「プロジェクトの種類」に[Silverlight]が追加されています。これを選択し、「テンプレート」から[Silverlightアプリケーション]を選びます。

[Silverlightアプリケーション]を選択
[Silverlightアプリケーション]を選択

 「新しいSilverlightアプリケーション」というダイアログボックスが表示されるので、「新しいWebプロジェクトの種類」を選び、リストから[ASP.NET Webサイト]を選択します。

リストから[ASP.NET Webサイト]を選択
リストから[ASP.NET Webサイト]を選択

 プロジェクトが作成され、新しいWebサイトに「MainPage.xaml」が作られてXAMLのコードが表示されます。

C1Knobコントロールの作成

 まず、グリッドに<ColumnDefinitions>を設定し、1行2列のグリッドにします。

<Grid x:Name="LayoutRoot" ShowGridLines="True">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="300"/>
        <ColumnDefinition Width="*"/>
    </Grid.ColumnDefinitions>

 ツールボックスにあるStackPanelコントロールをグリッドの左側に配置します。

	<StackPanel Grid.Column="0"></StackPanel>
</Grid>

 StackPanelの中にカーソルを置き、ツールボックスにあるC1Knobコントロールのアイコンをダブルクリックして作成します。

<StackPanel Grid.Column="0">
	<c1gauge:C1Knob></c1gauge:C1Knob>
</StackPanel>

 作成したC1Knobコントロールをカスタマイズします。まず、コードから参照できるようにコントロールに名前を付け、イベントハンドラ「ValueChanged」を作成します。ノブの値の範囲は0から120までとし、「Minimum」「Maximum」プロパティを設定します。また、ノブの動作範囲は、12時位置を0度として時計回りに200度の位置をスタートにし、ここから時計回りに270度の位置で終了するように、「StartAngle」「SweepAngle」プロパティを設定します。そして、ノブがマウスのドラッグで動くように「InteractionMode」プロパティの値を「Drag」に設定します。

<c1gauge:C1Knob x:Name="c1kb1" Width="200" ValueChanged="c1kb1_ValueChanged"
                VerticalAlignment="Center" Minimum="0" Maximum="120" StartAngle="200" 
                                    SweepAngle="270" Margin="0,30,0,0" InteractionMode="Drag">
</c1gauge:C1Knob>

 これで、次のようなノブが作成されます。プロジェクトを実行し、ノブをマウスでドラッグして動作することを確認します。

作成したノブ
作成したノブ

目盛りの数値ラベルと目盛り線の設定

 ノブが作成できたら、目盛りの数値ラベルと目盛り線を設定します。これは、C1Knobコントロールの「GaugeLabelクラス」と「GaugeMark」クラスを設定します。

 「GaugeLabel」は目盛りの数値ラベルを表すオブジェクトです。「Interval」プロパティは数値の間隔を指定します。例えば、このプロパティを「20」に設定すると、「Maximum」プロパティから「Minimum」プロパティの値の範囲で数値を20ごとに自動的に計算し、ラベルで設定してくれます。また、「Location」プロパティは、ノブのどの位置にラベルを表示するかを指定するプロパティで、ゲージの中心が「0」、ゲージの外縁が「1」になります。

 今回のノブでは、数値ラベルを20間隔で表示し、ノブの外側に表示するようにしています。

<c1gauge:C1GaugeLabel Interval="20" Location="1.5" />
作成した数値ラベル
作成した数値ラベル

 目盛り線は、「GaugeMark」クラスを使用します。目盛りの間隔は数値ラベルと同じで、「Interval」プロパティで目盛り線の間隔を、「Location」プロパティで目盛り線の位置を指定します。これで、数値ラベルと同じように「Maximum」プロパティから「Minimum」プロパティの値の範囲で、自動的に線の間隔を計算し設定してくれます。

 「GaugeMark」クラスを2つ設定すると、2種類の目盛り線を表示できます。ここでは、ノブの縁の内側と外側にそれぞれ違う感覚の目盛り線を設定します。

<c1gauge:C1GaugeMark Interval="10" />
<c1gauge:C1GaugeMark Interval="5" Location="1.15" />
※注

 目盛り線を特定の範囲に設定したい場合は、「From」プロパティと「To」プロパティで値の範囲を指定します。

<c1gauge:C1GaugeMark From="0" To="100" Interval="10" />

 目盛り線は、デフォルトでは青灰色の四角形として描画されますが、独自の目盛り線にカスタマイズすることもできます。その場合は、目盛り線を表示するためのテンプレートを作成し、このテンプレートを「Template」プロパティで指定します。

 ここでは、内側の目盛り線を紫色の太い線にカスタマイズします。テンプレートは、GridコントロールのResourceとして作成し、これを「Template」プロパティに設定します。目盛り線は、グラフィックスの四角形を作成しこれを割り当てる、という方法を使用します。

<!-- ゲージマークを表示するためのテンプレート -->
<Grid.Resources>
    <DataTemplate x:Key="MyMarkTemplate">
        <Rectangle Width="4" Height="18" Fill="BlueViolet" Stroke="Black" StrokeThickness=".5"/>
    </DataTemplate>
</Grid.Resources>

.................
.................

	<c1gauge:C1GaugeMark Interval="10" Template="{StaticResource MyMarkTemplate}"/>
	<c1gauge:C1GaugeMark Interval="5" Location="1.15" />
</c1gauge:C1Knob>
カスタマイズした目盛り線
カスタマイズした目盛り線

ButtonとTextBlockコントロールの作成

 C1Knobコントロールの下にButtonコントロールを2つ作成します。それぞれ、コントロールに名前を付けてClickイベントハンドラを作成しておきます。

    <Button x:Name="button1" Click="button1_Click" Content="Start" Width="100" Margin="0,30,0,0" />
    <Button x:Name="button2" Click="button2_Click" Content="Stop" Width="100" Margin="0,30,0,0" />
</StackPanel>

 また、右側の列のグリッドにTextBlockコントロールを作成します。コードから参照できるようにコントロールに名前を付け、グラデーションで塗りつぶしてドロップシャドウを設定してできあがりです。

    <TextBlock Grid.Column="1" x:Name="text1" FontSize="70" Text="00" Margin="50,100,0,0">
        <TextBlock.Foreground>
            <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
              <GradientStop Color="Yellow" Offset="0.0" />
              <GradientStop Color="LimeGreen" Offset="1.0" />
            </LinearGradientBrush>
        </TextBlock.Foreground>
                 
        <TextBlock.Effect>
            <DropShadowEffect Color="Black"></DropShadowEffect>
        </TextBlock.Effect>
    </TextBlock>
</Grid>
できあがったWebページ
できあがったWebページ

コードによるタイマー処理

 Webページが出来上がったら、コードタイマー処理を作成します。

タイマーの作成

 この処理は、「System.Windows.Threading」名前空間の「DispatcherTimer」クラスを使用するので「System.Windows.Threading」名前空間をインポートし、「DispatcherTimer」クラスのインスタンスをモジュールレベル変数で作成しておきます。

Visual Basic
Imports System.Windows.Threading

Partial Public Class MainPage
    Inherits UserControl

    Private WithEvents timer As New DispatcherTimer()
C#
using System.Windows.Threading;
namespace sl_timer_cs
{
    public partial class MainPage : UserControl
    {
        private DispatcherTimer timer = new DispatcherTimer();

 「DispatcherTimer」クラスは、指定した時間の間隔でイベントを発生するタイマーです。WindowsフォームのTimerコントロールと同様、Intervalプロパティでイベント発生の時間間隔を設定し、イベント「Tick」を発生させます。

 そこで、Webページのコンストラクタで、Intervalプロパティを1000ミリ秒に設定し、C#ではイベントハンドラを作成しておきます。

Visual Basic
Public Sub New()
	InitializeComponent()
    Timer.Interval = New TimeSpan(0, 0, 0, 0, 1000)
End Sub
C#
 public MainPage()
{
    InitializeComponent();
    timer.Interval = new TimeSpan(0, 0, 0, 0, 1000);
    timer.Tick += new EventHandler(timer_Tick);
}

ノブを動かした処理の作成

 次に、C1Knobコントロールのノブをユーザーが動かした時の処理を作成します。ユーザーがノブを動かすと、C1Knobコントロールには「ValueChanged」イベントが発生するので、このイベントハンドラでC1KnobコントロールのValueプロパティから設定値を取得します。ただし、Valueプロパティの値はdouble型なので一度整数に変換し、TextBlockに設定値を表示します。

Visual Basic
Private Sub c1kb1_ValueChanged(ByVal sender As System.Object, ByVal e As C1.Silverlight.PropertyChangedEventArgs(Of System.Double))
    Dim i As Int16
    i = c1kb1.Value
    text1.Text = i.ToString()
End Sub
C#
private void c1kb1_ValueChanged(object sender, C1.Silverlight.PropertyChangedEventArgs<double> e)
{
    Int16 i;
    i = (Int16)c1kb1.Value;
    text1.Text = i.ToString();
}

タイマー動作によるカウントダウン処理の作成

 次に、タイマーのTickイベントハンドラで、カウントダウンの処理を行います。

 まず、C1Knobコントロールの現在のノブの値をValueプロパティで取得して整数に変換します。そして、その数値から1を差し引き、C1KnobコントロールのValueプロパティに再設定します。こうすると、タイマーの動作に合わせてノブも自動的に数値が下がる方向に動くようになります。TextBlockにも数値を表示します。これで、1秒ごとにノブで設定した数値が1つずつ減っていきカウントダウンしていきます。

 もし、このノブの値が「0」になったら、タイマーを停止させます。これは、「DispatcherTimer」クラスのStopメソッドを実行します。

Visual Basic
Public Sub timer_Tick(ByVal sender As Object, ByVal e As EventArgs) Handles timer.Tick
	Dim i As Int16

    i = c1kb1.Value
    i -= 1
    If i < 0 Then
        timer.Stop()
    Else
        c1kb1.Value = i
        text1.Text = i.ToString
    End If
End Sub
C#
void timer_Tick(object sender, EventArgs e)
{
    Int16 i;

    i = (Int16)c1kb1.Value;
    i -= 1;
    if (i < 0)
    {
        timer.Stop();
    }
    else
    {
        c1kb1.Value = i;
        text1.Text = i.ToString();
    }
}

スタート・ストップボタンの処理

 2つのButtonコントロールでは、タイマーの停止と開始を実行します。これは、それぞれ「DispatcherTimer」クラスのStart・Stopメソッドを実行します。

Visual Basic
Private Sub button1_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    timer.Start()
End Sub

Private Sub button2_Click(ByVal sender As System.Object, ByVal e As System.Windows.RoutedEventArgs)
    timer.Stop()
End Sub
C#
private void button1_Click(object sender, RoutedEventArgs e)
{
    timer.Start();
}

private void button2_Click(object sender, RoutedEventArgs e)
{
    timer.Stop();
}
xamlコード全文
<UserControl xmlns:c1gauge="clr-namespace:C1.Silverlight.Gauge;assembly=C1.Silverlight.Gauge"  x:Class="sl_timer_cs.MainPage"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
    mc:Ignorable="d" d:DesignWidth="640" d:DesignHeight="480">
    
    <Grid x:Name="LayoutRoot" ShowGridLines="True">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="300"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>

        
        <!-- ゲージマークを表示するためのテンプレート -->
        <Grid.Resources>
            <DataTemplate x:Key="MyMarkTemplate">
                <Rectangle Width="4" Height="18" Fill="BlueViolet" Stroke="Black" StrokeThickness=".5"/>
            </DataTemplate>
        </Grid.Resources>

        <StackPanel Grid.Column="0">
            <c1gauge:C1Knob x:Name="c1kb1" Width="200" ValueChanged="c1kb1_ValueChanged"
                        VerticalAlignment="Center" Minimum="0" Maximum="120" StartAngle="200" 
                        SweepAngle="270" Margin="0,30,0,0" InteractionMode="Drag">

                <c1gauge:C1GaugeLabel Interval="20" Location="1.5" />
                <c1gauge:C1GaugeMark Interval="10" />
                <c1gauge:C1GaugeMark Interval="5" Location="1.15" />
            </c1gauge:C1Knob>

            <Button x:Name="button1" Click="button1_Click" Content="Start" Width="100" Margin="0,30,0,0" />
            <Button x:Name="button2" Click="button2_Click" Content="Stop" Width="100" Margin="0,30,0,0" />
        </StackPanel>

        <TextBlock Grid.Column="1" x:Name="text1" FontSize="70" Text="00" Margin="50,100,0,0">
    	    <TextBlock.Foreground>
                <LinearGradientBrush StartPoint="0,0" EndPoint="1,1">
                  <GradientStop Color="Yellow" Offset="0.0" />
                  <GradientStop Color="LimeGreen" Offset="1.0" />
                </LinearGradientBrush>
            </TextBlock.Foreground>
                     
            <TextBlock.Effect>
                <DropShadowEffect Color="Black"></DropShadowEffect>
            </TextBlock.Effect>
        </TextBlock>
    </Grid>
</UserControl>

まとめ

 アニメーションを使ったGUIは、ユーザーに直感的な操作を提示でき、「使いやすいページ」の印象を与えるとともに、新鮮で高度な技術を使ったページという印象も与えます。今回は、簡単なカウントダウンタイマーを作成しましたが、C1Knobコントロールはアイデア次第で色々な入力インターフェイスに使用できるコントロールと言えます。

参考文献

関連記事

製品情報

  • ブックマーク
  • LINEで送る
  • このエントリーをはてなブックマークに追加

著者プロフィール

  • 瀬戸 遥(セト ハルカ)

    8ビットコンピュータの時代からBASICを使い、C言語を独習で学びWindows 3.1のフリーソフトを作成、NiftyServeのフォーラムなどで配布。Excel VBAとVisual Basic関連の解説書を中心に現在まで40冊以上の書籍を出版。近著に、「ExcelユーザーのためのAccess再...

All contents copyright © 2005-2020 Shoeisha Co., Ltd. All rights reserved. ver.1.5