搜尋此網誌

2009年11月23日 星期一

Silverlight:Grid劃份區域 & 動態裁切範圍(Grid 、Clip 的使用)

本篇主要說明在C#內指定裁切範圍,順便提一下以「*」來指定Grid範圍的方法(基本上...這兩樣東西是可以分開說明)。


首先準備好Grid:

<Grid x:Name="LayoutRoot" Loaded="doClip" Width="400" Height="200">

  <Rectangle Width="400" Height="200" Fill="Red"/>
  <Grid ShowGridLines="True" x:Name="GridToClip" >
    <Grid.ColumnDefinitions>
     <ColumnDefinition Width="2*"/>
     <ColumnDefinition Width="5*"/>
    </Grid.ColumnDefinitions>
    <Ellipse Width="50" Height="50"
      Fill="Green" Grid.Column="1">
    <Ellipse.RenderTransform>
     <TranslateTransform X="-150"/>
    </Ellipse.RenderTransform>

    </Ellipse>
  </Grid>
</Grid>

以上使用Grid.Column將區域分成兩個部份,其中並沒有使用Grid.Clip元件對任何一個區域做裁切的動作。

另外在指定 Column各別寬度的部份,『Width="2*"』及『Width="5*"』將Grid總算度以 2:5 的比例做分配,Column為1(第二欄)的地方置放一個Ellipse元件,並橫跨第一欄及第二欄,當裁切完成時,我們可以明白分辦裁切的效果。

接著在頁面載入時加入以下程式,可指定裁切屬性及範圍:

private void doClip(object sender, RoutedEventArgs e)
{
 GridToClip.Clip = new RectangleGeometry()
 {
  Rect = new Rect(0, 0, 200, 100)
 };
}

其中

  new Rect(0,0,200,100)

紅字部份分別指定double型態的Top、Left、Bottom、Right

2009年11月18日 星期三

Silverlight:正確執行 HTTP Request(POST/GET)

在網路上使用POST或GET方式對伺服器要求服務簡是很普遍的行為,以下介紹在Silverlight上從事此行為的步驟。

☆要傳送一個POST/GET的動作,Silverlight有兩種方式:
1、WebClient
2、HttpWebRequest

本篇先介紹 WebClient

☆除了程式內容以外,在server端需要額外做一個步驟,才能使得Silverlight正常做到POST/GET的動作:
在server端設置「clientaccesspolicy.xml」或「crossdomain.xml」,兩者擇一即可,兩個xml的內容稍後會描述。


可直接在程式執行階段鍵入以下程式內容,建立WebClient:

WebClient wc = new WebClient();
wc.DownloadStringCompleted +=
  new DownloadStringCompletedEventHandler(wc_DownloadStringCompleted);
Uri uri =
  new Uri("http://2.latest.te-web-database.appspot.com
  /getTeacherIdByClassIdByWeb?aClassId=Creat");


wc.DownloadStringAsync(uri);

上述程式碼內紅字部份,請依據使用者欲連結的伺服器網域,輸入網域位置及POST/GET的內容,簡單說明程式步驟如下:
1、建立 WebClient物件(new WebClient)。
2、完成POST/GET動作後,建立欲導入的function(wc.DownloadStringCompleted += ...)。
3、建立Uri物件(Uri uri = new Uri(xxx))。
4、執行(wc.DownloadStringAsync(uri))。

另外別忘了建立DownloadStringCompleted所指定的function內容:

void wc_DownloadStringCompleted(object sender, DownloadStringCompletedEventArgs e)
{
if (e.Error == null)
{
MessageBox.Show(e.Result);
}
else
{
MessageBox.Show("else");
}
}

如果使用WebClient的方式,POST/GET成功後的回傳值將會在上一段程式的「e.Result」內。


執行httpRequest前最重要的事情,需將「clientaccesspolicy.xml」或「crossdomain.xml」設置到 Domain的根目錄(參考頁:http://community.dynamics.com/blogs/cesardalatorre/comments/9579.aspx):

選擇1、建立clientaccesspolicy.xml檔案,檔案內容如下:

<?xml version="1.0" encoding="utf-8"?>
 <access-policy>
  <cross-domain-access>
  <policy>
  <allow-from http-request-headers="*">
   <domain uri="*"/>
  </allow-from>
   <grant-to>
    <resource path="/" include-subpaths="true"/>
   </grant-to>
  </policy>
 </cross-domain-access>
</access-policy>


選擇2、建立crossdomain.xml檔案,檔案內容如下:

<?xml version="1.0"?>
<!DOCTYPE cross-domain-policy
  SYSTEM "http://www.macromedia.com/xml/dtds/cross-domain-policy.dtd">
<cross-domain-policy>
  <allow-http-request-headers-from domain="*" headers="*"/>
</cross-domain-policy>


以上兩個xml只需選擇一個,置於Domain的根目錄下,以本篇例子來說,就該將xml檔案放在「http://2.latest.te-web-database.appspot.com」之下。

2009年11月11日 星期三

Silverlight:在C#中改變Image の Source

以C#程式去改變一個Silverlight Image元件的Source屬性,這裡以兩張 png圖檔的變換來做範例。

首先請任意準備好兩張圖片檔案,各別取名為"enter.png"及"leave.png",在xaml檔案的<Grid>內加入以下敘述:

<Image x:Name="img" Source="leave.png" Width="100" Height="100"
  MouseEnter="enter" MouseLeave="leave">


為正常使用BitmapImage功能,在 cs檔開頭using部份加入以下敘述:

using System.Windows.Media.Imaging;

當滑鼠進入圖片範圍將會執行enter函式,離開圖片範圍則執行leave函式,兩個函式內容如下:

private void enter(object sender, MouseEventArgs e)
{
BitmapImage newImg =
       new BitmapImage(new Uri("enter.png", UriKind.Relative));
img.Source = newImg;
}

private void leave(object sender, MouseEventArgs e)
{
BitmapImage newImg =
       new BitmapImage(new Uri("leave.png", UriKind.Relative));
img.Source = newImg;
}


加入System.Windows.Media.Imaging後方可使用BitmapImage class,變換圖片的動作才能夠正常執行。

2009年11月10日 星期二

Silverlight:漸變顏色梯度

在Silverlight使用顏色梯度對元件的Fill屬性做設定已很平常,在效果的運用上,這裡介紹使物件漸淡的設定方法。



上圖由程式繪制出兩個<Rectangle>元件,其中一個使用線性漸變的顏色梯度設定,程式敘述如下:

<Grid x:Name="LayoutRoot">
  <Rectangle Width="200" Height="50" Fill="White"/>           
  <Rectangle Width="100" Height="100" Opacity="0.9" Grid.Row="1"
     Grid.Column="0" RadiusX="10" RadiusY="10">
    <Rectangle.RenderTransform>
      <TranslateTransform X="5" Y="-3"/>
    </Rectangle.RenderTransform>
    <Rectangle.Fill>
     <LinearGradientBrush EndPoint="0.7,0.5" StartPoint="0,0.5" >
       <GradientStop Color="#00000000" Offset="1"  />
       <GradientStop Color="#FF000000" Offset="0"/>
     </LinearGradientBrush>
    </Rectangle.Fill>
  </Rectangle>
</Grid>

這樣的設定,在元件可能被任意移動時,可做到將物件動態漸淡的效果。設定方法主要在顏色屬性的EndPointStartPoint數值、Color數值中Alpha值由FF至00互相調整,就能做到這樣的效果。(註:Alpha值指的即是 #FF000000中紅字部份的值)

2009年11月6日 星期五

Silverlight:Children使用Grid

先看到以下Silverlight敘述:

<Grid x:Name="LayoutRoot" Height="400" Width="800"
      ShowGridLines="True" Background="White">
  <Grid.RenderTransform>
    <TransformGroup>
      <TranslateTransform X="0" Y="10" />
    </TransformGroup>
  </Grid.RenderTransform>
  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>
  <Grid.ColumnDefinitions>
    <ColumnDefinition />
      <ColumnDefinition />
      <ColumnDefinition />
    </Grid.ColumnDefinitions>
  <Canvas x:Name="box1" Grid.Row="0" >
    <Canvas.RenderTransform>
      <TranslateTransform X="35" Y="10"/>
    </Canvas.RenderTransform>
      <Rectangle Width="100" Height="100" Fill="Red" Grid.Column="1"/>
  </Canvas>

</Grid>



在某些情況下(例如動態排列物件位置)使用Grid元件時,當我們將要將Silverlight元件丟進名為box1的Canvas物件內,並設定其位置到Grid的第1行第2列時(Row=0、Column=1),將物件置入box1後,直接在該物件上設定Grid.Row的屬性將行不通,例如:

<Canvas x:Name="box1" Grid.Row="0" >
  <Canvas.RenderTransform>
    <TranslateTransform X="35" Y="10"/>
  </Canvas.RenderTransform>
    <Rectangle Width="100" Height="100" Fill="Red" Grid.Column="1"/>
</Canvas>

以上敘述的Rectangle物件將不會被設定至Grid(0,1)的位置。而是乖乖的待在其所屬的parent Canvas元件的起始位置。

將以上<Grid>內改改變如下:

<Grid x:Name="LayoutRoot" Height="400" Width="800" Background="White">
  <Grid.RenderTransform>
    <TransformGroup>
      <TranslateTransform X="0" Y="10" />
    </TransformGroup>
  </Grid.RenderTransform>

  <Grid.RowDefinitions>
    <RowDefinition />
    <RowDefinition />
  </Grid.RowDefinitions>

  <Canvas x:Name="box1" Grid.Row="1" Grid.Column="1" >
    <Canvas.RenderTransform>
      <TranslateTransform X="0"/>
    </Canvas.RenderTransform>
    <Grid ShowGridLines="True" Width="870" x:Name="privateGridBox">
      <Grid.ColumnDefinitions>
        <ColumnDefinition />
        <ColumnDefinition />
        <ColumnDefinition />
       </Grid.ColumnDefinitions>
    </Grid>
  </Canvas>

</Grid>

將Silverlight元件置於在上敘box1元件的<Grid>內,可正常使用Grid功能。

2009年11月4日 星期三

Silverlight:使用元件內無指定的屬性,可能產生的問題

在從事修改Sliverlight內各元件的屬性,假若在.xaml檔內的元件沒有先行加入屬性的敘述,程式執行時,將無指對該屬性從事修改的動作(元件內無法找到指定的屬性),例如以下Ellipse元件:

<Ellipse x:Name="MyAnimatedRectangle" Stroke="Black" StrokeThickness="1"
  Width="50" Height="50" >

</Ellipse>


程式在執行中,若想使用 PlaneProjection對當下的Ellipse元件指定RotationX屬性值,則會發生找不到指定屬性的狀況。其解決方法即是在目標Ellipse內加入Projection內容(物件內必需被包入指定的屬性值,亦即程式執行當中再加入亦可):

<Ellipse x:Name="MyAnimatedRectangle" Stroke="Black" StrokeThickness="1"
  Width="50" Height="50" >
    <Ellipse.Projection>
     <PlaneProjection x:Name="pProject" RotationX="0" RotationY="0"/>
    </Ellipse.Projection>

</Ellipse>

假若沒有預先加入<Prjection>內容,程式執行屬性修改前加入以下程式碼亦可:

MyAnimatedRectangle.Projection = new PlaneProjection();

Silverlight:使物件移動至指定座標(RenderTransform)

開啟一個Silverlight專案(C#)後,在.xaml檔加入以下內容,產生一個Grid(即將以下內容整個放在<UserControl>及</UserControl>之間,若已有Grid,取代之):

  <Grid x:Name="LayoutRoot" Background="white" Width="450" Height="450">
        <Canvas Background="Red" x:Name="canvasForBackground" MouseLeftButtonDown="getMousePosition">
            <Canvas.Resources>
                <Storyboard x:Name="moveEllipse">
                    <DoubleAnimation x:Name="moveEllipse_moveX" 
           Storyboard.TargetName="MyAnimatedRectangle"
           Storyboard.TargetProperty="(Ellipse.RenderTransform).X"
                                     From="10" To="100" Duration="0:0:1"/>
                    <DoubleAnimation x:Name="moveEllipse_moveY" 
           Storyboard.TargetName="MyAnimatedRectangle"
           Storyboard.TargetProperty="(Ellipse.RenderTransform).Y"
                                     From="10" To="100" Duration="0:0:1"/>
                </Storyboard>
            </Canvas.Resources>
            <Ellipse x:Name="MyAnimatedRectangle" Stroke="Black"
         StrokeThickness="4" Fill="Red" Width="50" Height="50" >
                <Ellipse.RenderTransform>
                    <TranslateTransform X="200" Y="200"/>

                </Ellipse.RenderTransform>
            </Ellipse>
        </Canvas>
    </Grid>


上述內容中,有先設定好的Silverlight元件動畫:

            <Canvas.Resources>
                <Storyboard x:Name="moveEllipse">
                    <DoubleAnimation x:Name="moveEllipse_moveX"  Storyboard.TargetName="MyAnimatedRectangle" Storyboard.TargetProperty="(Ellipse.RenderTransform).X"
                                     From="10" To="100" Duration="0:0:1"/>
                    <DoubleAnimation x:Name="moveEllipse_moveY"  Storyboard.TargetName="MyAnimatedRectangle" Storyboard.TargetProperty="(Ellipse.RenderTransform).Y"
                                     From="10" To="100" Duration="0:0:1"/>
                </Storyboard>
            </Canvas.Resources>



在同一個Storyboard中,可以加入兩個DoubleAnimation(如上述Storyboard包函了「moveEllipse_moveX」、「moveEllipse_moveY」兩個DoubleAnimation),當名為「canvasForBackground」的Canvas元件被按下後,會進入getMousePosition函式,觸發此Storyboard動畫,相對應的C#程式內容如下:


using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using System.Windows.Browser;

namespace MoveWithMouse
{
public partial class MainPage : UserControl
{
public MainPage()
{
InitializeComponent();
}

private void getMousePosition(object sender, MouseButtonEventArgs e)
{
TranslateTransform tt =
MyAnimatedRectangle.RenderTransform as TranslateTransform;
Point pos;
pos = e.GetPosition(canvasForBackground);
moveEllipse_moveX.From = tt.X;
moveEllipse_moveX.To = pos.X - 25;
moveEllipse_moveY.From = tt.Y;
moveEllipse_moveY.To = pos.Y - 25;
moveEllipse.Begin();
}
}
}


其中「moveEllipse_moveX」即是.xaml檔中,Storyboard之下其中一個DoubleAnimation的名字,在程式中將其「From」的屬性改為當下Silverlight元件的位置。
其中有一行如「 moveEllipse_moveX.To = pos.X - 25;」,其需要減去25的原因在於此Ellipse元件的Width值為50,減去25之後,元件移動後,元件中心才會正確到達指定點。

Silverlight:簡單的3D屬性控制(RotationX、Y、Z))

開啟一個Silverlight專案(C#)後,在.xaml檔加入以下內容,產生一個Grid(即將以下內容整個放在<UserControl>及</UserControl>之間):


   <Grid x:Name="LayoutRoot" Width="450" Height="450" >
        <Canvas Background="Red" x:Name="canvasTop"
                MouseLeftButtonDown="getMousePosition" MouseMove="mouseMove" MouseLeave="unmouseDown" MouseLeftButtonUp="unmouseDown">
            <Ellipse x:Name="MyAnimatedRectangle" Stroke="Black" StrokeThickness="1"
                     Width="50" Height="50" >
                <Ellipse.Projection>
                    <PlaneProjection x:Name="pProject" RotationX="0" RotationY="0"/>
                </Ellipse.Projection>
                <Ellipse.RenderTransform>
                    <TranslateTransform X="200" Y="200"/>
                </Ellipse.RenderTransform>
                <Ellipse.Fill>
                    <LinearGradientBrush EndPoint="0.2,1" StartPoint="0.5,0">
                        <GradientStop Color="Black" Offset="0"/>
                        <GradientStop Color="#FFEEC5C5" Offset="1"/>
                    </LinearGradientBrush>
                </Ellipse.Fill>
            </Ellipse>
        </Canvas>
    </Grid>



上述的xaml內容,在名為canvasTop的Canvas元件中有四個mouse事件,即「MouseLeftButtomDown」、「MouseLeftButtonUp」、「MouseMove」、「MouseLeave」。事件發生時觸發的function:

MouseLeftButtomDown → getMousePosition()
MouseLeftButtonUp、MouseLeave → unmouseDown()
MouseMove → mouseMove()

與其對應的 .cs檔,程式內容如下:

using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace Rotation3D_OnMouse
{
public partial class MainPage : UserControl
{
bool onMouseDown = false;//if mouse click on canvas
Point currentPosition;
Point nextPosition;

public MainPage()
{
InitializeComponent();
}

private void getMousePosition(object sender, MouseButtonEventArgs e)
{
onMouseDown = true;
currentPosition = e.GetPosition(canvasTop);
}

private void mouseMove(object sender, MouseEventArgs e)
{
if (!onMouseDown) return;

nextPosition = e.GetPosition(canvasTop);
PlaneProjection pp = MyAnimatedRectangle.Projection as PlaneProjection;
double tmpX = nextPosition.Y - currentPosition.Y;
double tmpY = nextPosition.X - currentPosition.X;
pp.RotationX = tmpX;
pp.RotationY = tmpY;
}

private void unmouseDown(object sender, MouseEventArgs e)
{
onMouseDown = false;
}
}
}



觸發MouseLeftButtonDown後做MouseMove的動作,可對Silverlight目標物件做RotationX、RotationZ的動作。