スクリプティングとマウスイベント

スクリプティングとイベント

Silverlight では、オブジェクトが読み込まれたり、オブジェクトでマウスが押されたといったイベントが発生したときに JavaScript コードを実行できます。 このようなスクリプトを "イベントハンドラ" と呼びます。

イベントハンドラを定義するには、以下の手順に従ってください。

  1. XAML ファイルで、関数を呼び出すオブジェクトに以下の属性を追加する。

    someEvent="myFunction"

    ここで someEvent は応答するイベントであり、myFunction は イベントを処理する関数の名前です。

  2. JavaScript ファイルにおいて関数を定義します。(JavaScript ファイルの準備については、Silverlight プロジェクトの作成 を参照してください。)

サンプルを試してみましょう。Silverlight では、Canvas や図形要素は、 すべて MouseLeftButtonDown というイベントを持っており、 これはマウスポインタがその要素の上にあるときにマウスの左ボタンを押すと発生します。 ダイアログボックスを作成するために、イベントハンドラで JavaScript の alert 関数を使います。

<Canvas Height="300" Width="300"
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Background="transparent"
   MouseLeftButtonDown="helloworld">
   
  <TextBlock Text="click me"  FontSize="50"/>
</Canvas>
function helloworld() {
    alert("hello world");
}

イベントハンドラを宣言するためにパラメータを指定する必要はありませんが、 必要に応じてイベントを送出した要素を示す最初のパラメータ、"sender"、 イベントが持つデータを含むオブジェクトを示す2番目のパラメータ、"args" が使えます。

プロパティの設定

JavaScript を使って Silverlight オブジェクトのプロパティを設定できます。 プロパティが文字列や数値を取る場合、JavaScript で単純に設定するだけです。 プロパティが SIlverlight オブジェクトや、SolidColorBrush のような型変換を必要とする場合も、 文字列を使って値を設定できます。 これ以外の場合は、createFromXaml メソッドを使って新しいプロパティの値をインスタンス化する必要があります。

以下のサンプルは、CanvasMouseLeftButtonDown イベントを登録しています。 イベントハンドラでは、sender パラメータが Canvas へのアクセスを提供しています。 サンプルは CanvasBackground プロパティを赤に設定し、 Height プロパティの現在地を表示しています。

<Canvas Width="300" Height="300"
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Background="Transparent"
   MouseLeftButtonDown="changecolor">
   
  <TextBlock Text="click me"  FontSize="50"/>
</Canvas>
function changecolor(sender, args) {
    sender.background = "red";
    
    alert("Height is " + sender.Height);
}

付属プロパティの設定

Canvas.Top のような付属プロパティ(attached property)の値を JavaScript で設定するには、以下の構文を使ってください。

object["attachedPropertyName"] = value;

ここで attachedPropertyName 設定する付属プロパティの名前です。

以下の例では、マウスの左ボタンが押されたときに、 TextBlockCanvas.Top プロパティを 70 に設定しています。

<Canvas Width="300" Height="300"
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Background="Transparent">
    
  <TextBlock Text="click me"  FontSize="50" 
     MouseLeftButtonDown="changelocation" />
</Canvas>
function changelocation(sender, args) {
    
    sender["Canvas.Top"] = 70;
}

一般的なマウスイベント

UIElement オブジェクトは、MouseLeftButtonDownMouseLeftButtonUpMouseEnter (マウスが要素上を通過するときに発生)、MouseLeaveMouseMove(マウスが要素中を移動するときに発生) といったイベントを提供しています。 マウスイベントは、イベント発生時の X, Y 座標を提供する "args" オブジェクトを持ちます。

以下の例では、Ellipse の表現を変更するために 3 つのマウスイベントを使っています。

<Canvas
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   
  <Ellipse x:Name="e1" MouseMove="e1Move"
      MouseEnter="e1Enter" MouseLeave="e1Leave"
      MouseLeftButtonDown="e1Down" MouseLeftButtonUp="e1Up"
      Height="100" Width="100" Canvas.Left="80" Canvas.Top="30"
      Stroke="Black" StrokeThickness="10" Fill="LightBlue"/>
</Canvas>
function e1Enter(sender, args) {
    sender.stroke = "red";
}

function e1Leave(sender, args) {
    sender.stroke = "black";
}

function e1Down(sender, args) {
    sender.fill = "Green";
}

function e1Up(sender, args) {
    sender.fill = "LightBlue";
}

function e1Move(sender, args) {
    sender.fill = "yellow";
}

もうひとつ便利なイベントは Loaded イベントです。 このイベントは、たいていルート要素を宣言するときに登録しますが、 どの UIElement 要素でも Loaded を指定できます。 Loaded イベントは、Silverlight コントロールが表示されたときの最新の変更を 適用するよい機会を提供します。 以下の例では、Loaded イベントハンドラを使って、 EllipseFillBlue から Red に変えています。

<Canvas
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
  <Ellipse Loaded="ellipse_loaded"
     Height="200" Width="200" 
     Canvas.Left="30" Canvas.Top="30"
     Stroke="Black" StrokeThickness="10" Fill="LightBlue"/>
</Canvas>
function ellipse_loaded(sender, args) {
    sender.Fill = "Red";
}

オブジェクトへの名前付けと取り出し

前の例では、JavaScript イベントハンドラを使ってイベントが発生したオブジェクトを変更しました。 しかし、sender 以外のオブジェクトのメソッドを呼び出したり、プロパティを設定するには、どうすればよいでしょうか。 Silverlight の要素は findName と呼ばれるメソッドを提供しており、 子オブジェクトを取り出すことができます。 findName を使ってオブジェクトを取り出すには、 XAML でオブジェクトを定義するときに x:Name 属性を使って名前を与えなければなりません。

以下の例では、Ellipse に対して、親である Canvas の上でマウスの左ボタンが押されたときに Fill プロパティを変更しています。 Canvas がイベントを発生させると、 changeEllipseColor 関数が呼ばれ、sender には Canvas が渡されます。 この関数は sender.findName() を呼び出して、myEllipse という名前のオブジェクトを取り出し、 その Fill プロパティを Red に設定します。

<Canvas
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Background="Transparent"
   MouseLeftButtonDown="changeEllipseColor">
    
  <TextBlock Text="click me"  FontSize="50"/>
  <Ellipse x:Name="myEllipse" 
    Height="200" Width="200" 
    Canvas.Left="30" Canvas.Top="80"
    Stroke="Black" StrokeThickness="10" Fill="LightBlue"/>
</Canvas>
function changeEllipseColor(sender, args) {
    sender.findName("myEllipse").Fill = "red";
}

動的な Silverlight オブジェクトの作成

JavaScript で新たな Silverlight オブジェクトを作成するために createFromXaml メソッドが使えます。 ただし、createFromXaml メソッドを使う前に、まず Silverlight コントロールへの参照を取得する必要があります。

  • すでに Silverlight オブジェクトへの参照を持っていれば、これをホストしているコントロールへの参照を返す getHost メソッドが使えます。
  • そうでなければ、document.getElementById メソッドを使って、これを取り出します。

以下の例では、Canvas オブジェクトで左ボタンが押されるたびに、新たな Ellipse オブジェクトを作成して追加しています。

<Canvas Width="300" Height="300"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Background="Transparent"
    MouseLeftButtonDown="createEllipse">
    
  <TextBlock Text="click for circle"  FontSize="40"/>
</Canvas>
function createEllipse(sender, args) {
    
    var slControl = sender.getHost();
    var e = 
        slControl.content.createFromXaml(
            '<Ellipse Height="200" Width="200" Fill="Blue"/>');
    var canvas = sender;
    canvas.children.Add(e);
}

JavaScript では、+ 演算子を使って結合しない限り、複数の文字列を1行におさめる必要があります。 また、<Ellipse> XAML 文字列中では、シングルクォート(')とダブルクォート(") が使われていることに注意してください。 JavaScript の文字列で最初と最後にシングルクォートを使うことで、XAML 文字列の値としてダブルクォートを使うことができます。

XAML 文字列処理による、動的な Silverlight オブジェクトの作成

前述したサンプルでは、同じ XAML をあるページに一度以上追加することが予期せぬ副作用を招く可能性について示しました。XAML でオブジェクトを追加したい場合は、毎回 XAML に変更を加える必要があります。これは呼び出す直前に XAML 文字列を追加すればできますが、ここでは Ellipse の 3 つのプロパティを変更して、このページに複数のオブジェクトを実際に作成してみましょう。

<Canvas Width="300" Height="300"
    xmlns="http://schemas.microsoft.com/client/2007"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Background="Transparent"
    MouseLeftButtonDown="createEllipse2">
    
  <TextBlock Text="click for Lots of circles"  FontSize="20"/>
</Canvas>
var opacitychange = 1;
var canvastop = 0;
var canvasleft = 0;
function createEllipse2(sender, args) {
    
    var slControl = sender.getHost();
    xamlstring = '<Ellipse Height="10" Width="10" Fill="Red"';
    xamlstring += " Opacity = '" + (opacitychange-=0.1) + "'";
    xamlstring += " Canvas.Left = '" + (canvasleft+=15) + "'";
    xamlstring += " Canvas.Top = '" + (canvastop+=15) + "'";
    xamlstring += "/>";
    var e = slControl.content.createFromXaml(xamlstring);
    var canvas = sender;
    canvas.children.Add(e);
}

アニメーションの対話的制御

アニメーション を制御するためにイベントハンドラが使えます。 制御したい Storyboard に名前を割り当て、これを対話的に制御するために beginStopPauseResume メソッドを使います。 Storyboard を自動的に開始させないためには、 EventTrigger の中で宣言する代わりに、これをリソースとして宣言します。

<Canvas
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
   
  <Canvas.Resources>

    <Storyboard x:Name="animation"
      Storyboard.TargetName="e1"
      Storyboard.TargetProperty="(Canvas.Left)">
      <DoubleAnimation RepeatBehavior="Forever" To="300"/>
    </Storyboard>

  </Canvas.Resources>
  
  <Ellipse x:Name="e1"
      Height="20" Width="20" Canvas.Left="30" Canvas.Top="30">
    <Ellipse.Fill>
      <RadialGradientBrush GradientOrigin="0.75,0.25">
        <GradientStop Color="White" Offset="0.0" />
        <GradientStop Color="Black" Offset="0.5" />        
      </RadialGradientBrush>    
    </Ellipse.Fill>
  </Ellipse>
  
  <Canvas MouseLeftButtonDown="animation_stop" Canvas.Left="20" Canvas.Top="60">
    <Rectangle Stroke="Black" 
       Height="40" Width="40" RadiusX="5" RadiusY="5">
      <Rectangle.Fill>
        <RadialGradientBrush GradientOrigin="0.75,0.25">
          <GradientStop Color="Orange" Offset="0.0" />
          <GradientStop Color="Red" Offset="1.0" />        
        </RadialGradientBrush>
      </Rectangle.Fill>       
    </Rectangle>
    <TextBlock Canvas.Left="5" Canvas.Top="5">stop</TextBlock> 
  </Canvas>
  
  <Canvas MouseLeftButtonDown="animation_pause" 
     Canvas.Left="70" Canvas.Top="60">
    <Rectangle Stroke="Black" 
       Height="40" Width="50" RadiusX="5" RadiusY="5">
      <Rectangle.Fill>
        <RadialGradientBrush GradientOrigin="0.75,0.25">
          <GradientStop Color="Yellow" Offset="0.0" />
          <GradientStop Color="Orange" Offset="1.0" />        
        </RadialGradientBrush>
      </Rectangle.Fill>       
    </Rectangle>
    <TextBlock Canvas.Left="5" Canvas.Top="5">pause</TextBlock> 
  </Canvas>
  
  <Canvas MouseLeftButtonDown="animation_begin" Canvas.Left="130" Canvas.Top="60">
    <Rectangle Stroke="Black" RadiusX="5" RadiusY="5"
       Height="40" Width="50">
      <Rectangle.Fill>
        <RadialGradientBrush GradientOrigin="0.75,0.25">
          <GradientStop Color="LimeGreen" Offset="0.0" />
          <GradientStop Color="Green" Offset="1.0" />        
        </RadialGradientBrush>
      </Rectangle.Fill>
    </Rectangle>
    <TextBlock Canvas.Left="5" Canvas.Top="5">begin</TextBlock> 
  </Canvas>
</Canvas>
function animation_stop(sender, args) {
    sender.findName("animation").stop();
}

function animation_pause(sender, args) {
    sender.findName("animation").pause();
}

function animation_begin(sender, args) {
    sender.findName("animation").begin();
}

getElementById メソッドの使用

(HTML イベントハンドラのような)Silverlight イベントによって開始されないスクリプトを書くときは、 findNamegetHost にアクセスできる sender パラメータがありません。 この場合、document.getElementById() を使って Silverlight コントロールを見つけ出してから、 このコントロールの findName メソッドを呼び出します。

以下の例では、document.getElementById() メソッドを使って sl8 という名前の Silverlight コントロールを見つけています。 そして、コントロールの findName メソッドを使って、 myEllipse という名前の Silverlight オブジェクトを取り出し、 赤で塗りつぶしています。

<Canvas
   xmlns="http://schemas.microsoft.com/client/2007"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
   Background="Transparent"
   MouseLeftButtonDown="changeEllipseColor2">
   
  <TextBlock Text="click me"  FontSize="50"/>
  <Ellipse x:Name="myEllipse" 
    Height="200" Width="200" 
    Canvas.Left="30" Canvas.Top="80"
    Stroke="Black" StrokeThickness="10" Fill="LightBlue"/>
</Canvas>
function changeEllipseColor2() {
    var sl9 = document.getElementById("sl9");
    sl9.content.findName("myEllipse").fill = "red";

}

このサンプルでは、Sys.Silverlight.createObject() を呼び出したときに ホスト用の HTML ファイルで作成した Silverlight コントロールの ID が sl9 です。 これは、part 1: Silverlight プロジェクトの作成 ドキュメントで解説しました。


        // Retrieve the div element you created in the previous step.
        var mySilverlightPluginHost = document.getElementById("sl9Host");
        createMySilverlightPlugin();

        Silverlight.createObject(
             "sl9.xaml", 
             sl9Host, 
             "sl9",
             {
                  width:'300', 
                  height:'300', 
                  inplaceInstallPrompt:false, 
                  background:'#D6D6D6', 
                  isWindowless:'false', 
                  framerate:'24', 
                  version:'1.0'},
             {onError:null, onLoad:null},
             null);


次のステップ

次のトピックは、サンプルコード です。