搜尋此網誌

顯示具有 Silverlight 標籤的文章。 顯示所有文章
顯示具有 Silverlight 標籤的文章。 顯示所有文章

2010年5月7日 星期五

WPF : Translate & Rotate

以Grid來舉例,在Grid.RenderTransform時,先做「TranslateTransform」或是先做「RotateTransform」是有差別的:

確實以(0,0)點做Rotate,意即先Rotate再做Translate:

<Grid.RenderTransform>
 <TransformGroup>
  <RotateTransform CenterX="0" CenterY="0" Angle="0"
  x:Name="Crash_MidFront_Rotate"/>
  <TranslateTransform X="560" Y="300"/>
 </TransformGroup>
</Grid.RenderTransform>


反之,將Translate放在Rotate之前,會先做Translate,再以(0,0)點做Rotate

2010年4月14日 星期三

Silverlight : Point Animation of Storyboard

運用Path元件中 LineSegment來製造3D的假像,以下紀錄對於LineSegment中 Point動畫的設定:


<Storyboard x:Name="BoxSide_LeftSide_Back" Duration="0:0:1" >
 <PointAnimation x:Name="PointMove_Left_TL"
  Storyboard.TargetName="BoxSide_LeftSide_TL"
  Storyboard.TargetProperty="(LineSegment.StartPoint)"
  From="0,0" To="0,0"/>
 <PointAnimation x:Name="PointMove_Left_TR"
  Storyboard.TargetName="BoxSide_LeftSide_TR"
  Storyboard.TargetProperty="(LineSegment.Point)"
  From="0,0" To="0,0"/>

 <PointAnimation x:Name="PointMove_Left_BL"
  Storyboard.TargetName="BoxSide_LeftSide_BL"
  Storyboard.TargetProperty="(LineSegment.Point)"
  From="0,0" To="0,0"/>
 <PointAnimation x:Name="PointMove_Left_BR"
  Storyboard.TargetName="BoxSide_LeftSide_BR"
  Storyboard.TargetProperty="(LineSegment.Point)"
  From="0,0" To="0,0"/>
</Storyboard>

其中一個Path元件的內容如下:

<Path  x:Name="BoxSide_BackSide" Stroke="Gold">
 <Path.RenderTransform>
  <TranslateTransform X="200" Y="0"/>
 </Path.RenderTransform>
 <Path.Fill>
  <LinearGradientBrush StartPoint="0,0" EndPoint="0,1" >
   <GradientStop Color="#FF770000" Offset="0.0"/>
   <GradientStop Color="Black" Offset="1.0"/>
  </LinearGradientBrush>
 </Path.Fill>
 <Path.Data>
  <PathGeometry >
   <PathFigure StartPoint="90,100" IsClosed="True"   
    x:Name="BoxSide_BackSide_TL">
    <LineSegment Point="310,100" x:Name="BoxSide_BackSide_TR"/>
    <LineSegment Point="300,150" x:Name="BoxSide_BackSide_BR"/>
    <LineSegment Point="100,150" x:Name="BoxSide_BackSide_BL"/>
   </PathFigure>
  </PathGeometry>
 </Path.Data>
</Path>



假若Target直接指定Path元件,則TargetProperty設定值為:

Storyboard.TargetProperty=
 "(Path.Data).(PathGeometry.Figures)[0].
 (PathFigure.Segments)[0].(LineSegment.Point)"

可做到的效果(按下box前端及右端做上下拖拽):Box

2010年3月1日 星期一

Silverlight、C#:Unicode轉換

在C#中可使用以下程式碼對字串轉換為Unicode或將Unicode轉換為字元:

Encode

using System.Text;

private string StringToUnicode(string srcText)
{
  string dst = "";
  char[] src = srcText.ToCharArray();
  for (int i = 0; i < src.Length; i++)
  {
   byte[] bytes = Encoding.Unicode.GetBytes(src[i].ToString());
   string str = @"\u" + bytes[1].ToString("X2") + bytes[0].ToString("X2");
   dst += str;
  }
  return dst;
}

Decode

using System.Globalization;

private string UnicodeToString(string srcText)
{
string dst = "";
string src = srcText;
int len = srcText.Length / 6;

for (int i = 0; i <= len - 1; i++)
{
  string str = "";
  str = src.Substring(0, 6).Substring(2);
  src = src.Substring(6);
  byte[] bytes = new byte[2];
  bytes[1] =  
   byte.Parse(int.Parse
    (str.Substring(0,2),NumberStyles.HexNumber).ToString());
  bytes[0] = byte.Parse(int.Parse
    (str.Substring(2,  2),NumberStyles.HexNumber).ToString());
  dst += Encoding.Unicode.GetString(bytes);
  }
  return dst;
}


但上述程式碼中,Decode的部份在Slilverlight會出現「... is inaccessable due to its protection level」的錯誤,請改為以下內容,程式即可正常編譯:
Decode at Silverlight

string UnicodeToString(string srcText)
{
 string dst = "";
 string src = srcText;
 int len = srcText.Length / 6;

 for (int i = 0; i <= len - 1; i++)
 {
  string str = "";
  str = src.Substring(0, 6).Substring(2);
  src = src.Substring(6);
  byte[] bytes = new byte[2];
  bytes[1] = byte.Parse(int.Parse(str.Substring(0, 2),
   NumberStyles.HexNumber).ToString());
  bytes[0] = byte.Parse(int.Parse(str.Substring(2, 2),
   NumberStyles.HexNumber).ToString());

  Encoding enc = Encoding.GetEncoding("utf-16");
  dst += enc.GetString(bytes, 0, bytes.Length);

 }
  return dst;
}

2010年1月25日 星期一

Silverlight & Game:Puzzlies - Part 2


執行結果
下載原始檔


前一篇已將Puzzles中移動區塊的功能寫畢,接著我們加入「打散」的動作。

1.同前一篇的步驟新增一個類別,並命名為「shuffle」

shuffle.cs

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ImageClip_Puzzles
{
 public class shuffle
 {
  Random r = new Random();
  public void randomMove(
   imageBox[] ibArray,int[,] posArr,int count,
   int imageSize,int gridWidth){
  for (int i = 0; i < count; i++)
  {
   int moveValue = addMove();
   int moveIndex = 0;
   if (r.Next(0, 2) == 0)//do x
   {
    if (moveValue < 0) // '-'
    {
     if (ibArray[0].colIndex <= 0)
     {
       moveIndex = posArr[ibArray[0].rowIndex,
       ibArray[0].colIndex + 1];
       posArr[ibArray[0].rowIndex,
           ibArray[0].colIndex + 1] = 0;
       posArr[ibArray[0].rowIndex,
           ibArray[0].colIndex] = moveIndex;
     }
     else
     {
      moveIndex = posArr[ibArray[0].rowIndex,
      ibArray[0].colIndex - 1];
      posArr[ibArray[0].rowIndex,
          ibArray[0].colIndex - 1] = 0;
      posArr[ibArray[0].rowIndex,
          ibArray[0].colIndex] = moveIndex;
     }
    }
    else // '+'
    {
     if (ibArray[0].colIndex >= (gridWidth - 1))
     {
      moveIndex = posArr[ibArray[0].rowIndex,
                ibArray[0].colIndex - 1];
      posArr[ibArray[0].rowIndex,
          ibArray[0].colIndex - 1] = 0;
      posArr[ibArray[0].rowIndex,
          ibArray[0].colIndex] = moveIndex;
     }
     else
     {
      moveIndex = posArr[ibArray[0].rowIndex,
                ibArray[0].colIndex + 1];
      posArr[ibArray[0].rowIndex,
          ibArray[0].colIndex + 1] = 0;
      posArr[ibArray[0].rowIndex,
          ibArray[0].colIndex] = moveIndex;
     }
    }
   }
   else // do y
   {
    if (moveValue < 0) // '-1' = 'down'
    {
     if (ibArray[0].rowIndex <= 0) // move down (r+)
     {
      moveIndex =
       posArr[ibArray[0].rowIndex + 1, ibArray[0].colIndex];
      posArr[ibArray[0].rowIndex + 1,
          ibArray[0].colIndex] = 0;
      posArr[ibArray[0].rowIndex,
          ibArray[0].colIndex] = moveIndex;
     }
     else // move up (r-)
     {
      moveIndex =
       posArr[ibArray[0].rowIndex - 1, ibArray[0].colIndex];
      posArr[ibArray[0].rowIndex - 1,
          ibArray[0].colIndex] = 0;
      posArr[ibArray[0].rowIndex,
          ibArray[0].colIndex] = moveIndex;
     }
    }
    else // '1' = 'up'
    {
     if (ibArray[0].rowIndex >= (gridWidth - 1))
     {
      moveIndex =
       posArr[ibArray[0].rowIndex - 1, ibArray[0].colIndex];
      posArr[ibArray[0].rowIndex - 1,
          ibArray[0].colIndex] = 0;
      posArr[ibArray[0].rowIndex,
          ibArray[0].colIndex] = moveIndex;
     }
     else
     {
      moveIndex =
       posArr[ibArray[0].rowIndex + 1, ibArray[0].colIndex];
      posArr[ibArray[0].rowIndex + 1,
          ibArray[0].colIndex] = 0;
      posArr[ibArray[0].rowIndex,
          ibArray[0].colIndex] = moveIndex;
     }
    }
   }
   int tmpColIndex = ibArray[moveIndex].colIndex;
   int tmpRowIndex = ibArray[moveIndex].rowIndex;
   ibArray[moveIndex].moveToDirectly(
             ibArray[0].rowIndex - tmpRowIndex,
             ibArray[0].colIndex - tmpColIndex);
   ibArray[0].moveToDirectly(
             tmpRowIndex - ibArray[0].rowIndex,
             tmpColIndex - ibArray[0].colIndex);
   }
  }
  public int addMove()
  {
   if (r.Next(0, 2) == 0)// '+'
   {
    return 1;
   }
   else // '-'
   {
    return -1;
   }
  }
 }
}


除了打散圖片區塊會使用到的.cs檔以外,我還需要在原本的程式中插入幾個Function:
MainPage.xaml.cs
1.加入全域變數int[,] imagePos。
2.新增shuffle物件。

 int[,] imagePos;//use in postion record
 shuffle shu = new shuffle();

3.在 loadImg(),Function最尾端加入以下程式內容:

shu.randomMove(IBArray, imagePos, 50, imageSize, gridNum);


a.在程式執行前先建立了一個名為shu的shuffle物件。
b.程式將圖片區塊建立結束後,使用shuffle物件打散圖片區塊的位置。
c. 參數: randomMove(圖片區塊陣列,當前圖片區塊位置,圖片打散移動次數,圖片圖素大小,寬度)

2010年1月20日 星期三

Silverlight & Game:Puzzlies - Part 1

寫個Puzzlies小遊戲吧!
遊戲內容非常單純,移動3 x 3或 N x N的圖片區塊,恢復為完整的圖即成功。

本篇內容,先建立Puzzles的骨架及基本動作,其中我們一共會建立兩個 .xaml檔及一個.cs檔,另外需匯入一張圖片,檔案名稱如下:
 a. MainPage.xaml
 b. imageBox.xaml
 c. myRecorder.cs
 d. 圖片:imgs/Orz.png
(置於 imgs 資料夾之下)

1.建立一個新的Silverlight Applciation專案,在這裡我將專案名稱命為「ImageClip_Puzzlies」,以下為完整MainPage.xaml內容:

<UserControl x:Class="ImageClip_Puzzles.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" Loaded="loadImg">
 <Grid  Background="Gray" Width="500" Height="500"
    VerticalAlignment="Center" HorizontalAlignment="Center" >
  <Grid x:Name="PuzzlesTop" >
   <Grid.ColumnDefinitions>
    <ColumnDefinition Width="10"/>
    <ColumnDefinition Width="*"/>
    <ColumnDefinition Width="10"/>
  </Grid.ColumnDefinitions>
  <Grid.RowDefinitions>
   <RowDefinition Height="10"/>
   <RowDefinition Height="*"/>
   <RowDefinition Height="10"/>
  </Grid.RowDefinitions>
   <Grid Grid.Column="1" Grid.Row="1">
    <Rectangle Fill="Black"/>
   </Grid>
  </Grid>
  <TextBlock Text="sys" x:Name="sysMsg" FontSize="12"
      VerticalAlignment="Top" HorizontalAlignment="Center">
   <TextBlock.RenderTransform>
    <TranslateTransform X="0" Y="-20"/>
   </TextBlock.RenderTransform>
  </TextBlock>
 </Grid>    
</UserControl>

2.接著是imageBox.xaml的內容:

<UserControl x:Class="ImageClip_Puzzles.imageBox"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

 Width="Auto" Height="Auto" x:Name="imageTop"  >    
 <Canvas Height="600" Width="600" x:Name="imageCanvas">
  <Canvas.Resources>
   <Storyboard x:Name="moveImage_Direct_Up" SpeedRatio="5">
    <DoubleAnimation x:Name="UpAnima"
     Storyboard.TargetName="imageGrid"
     Storyboard.TargetProperty="(Canvas.Top)"
     From="0" To="0" Duration="0:0:1"  AutoReverse="False"/>
    <DoubleAnimation x:Name="borderAnima_Up"
     Storyboard.TargetName="imageBorder"
     Storyboard.TargetProperty="(Border.RenderTransform).Y"
     From="0" To="0" Duration="0:0:1" AutoReverse="False"/>
   </Storyboard>
   <Storyboard x:Name="moveImage_Direct_Left" SpeedRatio="5">
    <DoubleAnimation x:Name="LeftAnima"
     Storyboard.TargetName="imageGrid"
     Storyboard.TargetProperty="(Canvas.Left)"
     From="0" To="0" Duration="0:0:1"  AutoReverse="False"/>

    <DoubleAnimation x:Name="borderAnima_Left"
     Storyboard.TargetName="imageBorder"
     Storyboard.TargetProperty="(Border.RenderTransform).X"
     From="0" To="0" Duration="0:0:1" AutoReverse="False"/>
   </Storyboard>
  </Canvas.Resources>
  <Grid Canvas.Top="0" Canvas.Left="0"
   Width="480" Height="480" x:Name="imageGrid" >
   <Image Source="imgs/Orz.png" Stretch="Fill" x:Name="imageContent">
    <Image.Clip>
     <RectangleGeometry Rect="0,0,160,160 " >
     <RectangleGeometry.Transform>
      <TranslateTransform X="0" Y="0" x:Name="ImageAreaTransform"/>
     </RectangleGeometry.Transform>
     </RectangleGeometry>
    </Image.Clip>
   </Image>
  </Grid>
  <Border BorderBrush="#FF666666" BorderThickness="5" x:Name="imageBorder">
   <Border.RenderTransform>
    <TranslateTransform X="0" Y="0" x:Name="boardPosition"/>
   </Border.RenderTransform>
   <Rectangle x:Name="imageColor"
    Width="155" Height="155" Fill="Red" Opacity="0.01"/>
  </Border>
  <Grid Visibility="Visible">
   <Grid.RenderTransform>
    <TranslateTransform X="5" Y="10" x:Name="msgPos"/>
   </Grid.RenderTransform>
   <Grid.RowDefinitions>

    <RowDefinition Height="14"/>
    <RowDefinition Height="14"/>
    <RowDefinition Height="14"/>
    <RowDefinition Height="14"/>
    <RowDefinition Height="14"/>
   </Grid.RowDefinitions>
   <TextBlock x:Name="imgSysMsg1" Text="" FontSize="12" Grid.Row="0"/>
   <TextBlock x:Name="imgSysMsg2" Text="" FontSize="12" Grid.Row="1"/>
   <TextBlock x:Name="imgSysMsg3" Text="" FontSize="12" Grid.Row="2"/>
   <TextBlock x:Name="imgSysMsg4" Text="" FontSize="12" Grid.Row="3"/>
   <TextBlock x:Name="imgSysMsg5" Text="" FontSize="12" Grid.Row="4"/>
  </Grid>
 </Canvas>
</UserControl>


3.別忘了 mainPage.xaml及imageBox.xaml的 .cs內容:

mainPage.xaml

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 ImageClip_Puzzles
{
 public partial class MainPage : UserControl
 {
  private void SysMsg(string msg)
  {
   sysMsg.Text = msg;
  }
  int gridNum = 3;
  int imageSize = 160;
  Point[,] imagePos;
  imageBox[] IBArray;

  public MainPage()
  {
   InitializeComponent();
  }
  private void loadImg(object sender, RoutedEventArgs e)
  {
   imagePos = new Point[gridNum, gridNum];
   IBArray = new imageBox[gridNum * gridNum];
   for (int i = 0; i < gridNum; i++)
   {
    for (int j = 0; j < gridNum; j++)
    {
     imageBox ib = new imageBox();
     int indexOfAll = i * gridNum + j;
     IBArray[indexOfAll] = ib;

     ib.MouseLeftButtonDown += onImageClick;
     ib.moveImage_Direct_Up.Completed += moveIsFinish;
     ib.moveImage_Direct_Left.Completed += moveIsFinish;

     ib.setInfo(indexOfAll,i, j, gridNum, imageSize);
     PuzzlesTop.Children.Add(ib);
     ib.setGridPosition(1, 1);
     imagePos[i, j] =
      new Point(j * imageSize, i * imageSize);
}
}
BArray[0].setImageColor(0xFF, 0x00, 0x00);
}
bool imgIsMoving = false;
private void onImageClick(object sender, MouseButtonEventArgs e)
{
SysMsg("imgIsMoving : " + imgIsMoving.ToString());
if (imgIsMoving) return;
imgIsMoving = true;
imageBox uc = sender as imageBox;
string dir = getPic1(IBArray[uc.indexOfAllIBArray].rowIndex,
IBArray[uc.indexOfAllIBArray].colIndex);
uc.moveImageTo(dir);
switch (dir)
{
case "up":
IBArray[0].moveImageTo("down");
break;
case "down":
IBArray[0].moveImageTo("up");
break;
case "left":
IBArray[0].moveImageTo("right");
break;
case "right":
IBArray[0].moveImageTo("left");
break;
default:
imgIsMoving = false;
break;
}
}
private void moveIsFinish(object sender, EventArgs e)
{
Storyboard sb = (Storyboard)sender;
imageBox tmpImageBox =
(imageBox) sb.GetValue(myRecorder.record_ImageBox);
if (tmpImageBox.indexOfAllIBArray == 0) return;
int tmpRIndex = tmpImageBox.rowIndex;
int tmpCIndex = tmpImageBox.colIndex;

tmpImageBox.resetCurrentPosition(IBArray[0].rowIndex,
IBArray[0].colIndex);
IBArray[0].resetCurrentPosition(tmpRIndex, tmpCIndex);

imgIsMoving = false;
}
private string getPic1(int r, int c)
{
if (((r - 1) == IBArray[0].rowIndex)
&& (c == IBArray[0].colIndex))
// at down of Pic0 - - -> (r-1,c) then the imagemove 'up'
{
return "up";
}
else if (((r + 1) == IBArray[0].rowIndex)
&& (c == IBArray[0].colIndex))
//at top of Pic0 - - -> (r+1,c) then the image move 'down'
{
return "down";
}
else if ((r == IBArray[0].rowIndex)
&& ((c-1) == IBArray[0].colIndex))
//at right of Pic0 - - -> (r,c-1) then the image move 'left'
{
return "left";
}
else if ((r == IBArray[0].rowIndex)
&& ((c + 1) == IBArray[0].colIndex))
{
return "right";
}
else
{
return "stay";
}
}
private void showImageBoxMsg(imageBox ib)
{
ib.SysMsg("ib name : " + ib.Name,
    ", indexOfArrlyIBArray : " + ib.indexOfAllIBArray.ToString(),
    ", IBArray postion on " + ib.indexOfAllIBArray.ToString(),
    ", rowIndex : " + IBArray[ib.indexOfAllIBArray].rowIndex.ToString(),
    ", cowIndex : " + IBArray[ib.indexOfAllIBArray].colIndex.ToString());
}
}
} 


imageBox.xaml

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 ImageClip_Puzzles
{
public partial class imageBox : UserControl
{
 int separaNum = 3;
 int imgSize = 160;
 public int rowIndex = 0;
 public int colIndex = 0;
 public int orgiRowIndex = 0;
 public int orgiColIndex = 0;
 public int indexOfAllIBArray = 99;

 Point currentBorderPosition = new Point();
 public imageBox()
 {
  InitializeComponent();
 }
 public void setInfo(int indexOfArray,int rIndex,
      int cIndex,int separateNum,int imageSize)
 {
  indexOfAllIBArray = indexOfArray;
  separaNum = separateNum;
  imgSize = imageSize;
  imageUV(rIndex, cIndex);
  this.Name =
   "R(" + rIndex.ToString() + ")C(" + cIndex.ToString() + ")";
  rowIndex = rIndex;
  colIndex = cIndex;
  orgiRowIndex = rIndex;
  orgiColIndex = cIndex;
  animaRecordInfo(indexOfArray);
 }
 private void animaRecordInfo(int index)//, string name)
 {
  moveImage_Direct_Up.SetValue(myRecorder.record_ImageBox, this);
  moveImage_Direct_Left.SetValue(myRecorder.record_ImageBox, this);
 }
 private void imageUV(int indexU,int indexV)
 {
  ImageAreaTransform.X = indexV * 160;
  ImageAreaTransform.Y = indexU * 160;
  this.boardPosition.X = ImageAreaTransform.X;
  this.boardPosition.Y = ImageAreaTransform.Y;
  currentBorderPosition =
     new Point(ImageAreaTransform.X,ImageAreaTransform.Y);
  msgPos.X = ImageAreaTransform.X;
  msgPos.Y = ImageAreaTransform.Y;
 }
 public void setGridPosition(int rowIndex, int colIndex)
 {
  this.SetValue(Grid.RowProperty, rowIndex);
  this.SetValue(Grid.ColumnProperty, colIndex);
 }
 public void setImageColor(byte r, byte g, byte b)
 {
  Color c = Color.FromArgb(255, r, g, b);
  imageColor.Fill = new SolidColorBrush(c);
  imageColor.Opacity = 0.7;
 }
 public void SysMsg(string msg)
 {
  imgSysMsg1.Text = msg;
 }
 public void SysMsg(string msg1, string msg2)
 {
  imgSysMsg1.Text = msg1;
  imgSysMsg2.Text = msg2;
 }
 public void SysMsg(string msg1, string msg2, string msg3)
 {
  imgSysMsg1.Text = msg1;
  imgSysMsg2.Text = msg2;
  imgSysMsg3.Text = msg3;
 }
 public void SysMsg(string msg1, string msg2,
           string msg3, string msg4)
 {
  imgSysMsg1.Text = msg1;
  imgSysMsg2.Text = msg2;
  imgSysMsg3.Text = msg3;
  imgSysMsg4.Text = msg4;
 }
 public void SysMsg(string msg1, string msg2,
           string msg3, string msg4, string msg5)
 {
  imgSysMsg1.Text = msg1;
  imgSysMsg2.Text = msg2;
  imgSysMsg3.Text = msg3;
  imgSysMsg4.Text = msg4;
  imgSysMsg5.Text = msg5;
 }
 public void moveImageTo(string dir)
 {
  SysMsg("");
  switch (dir)
  {
   case "up":
    this.UpAnima.From =
     Convert.ToDouble( imageGrid.GetValue(Canvas.TopProperty));
    this.UpAnima.To = this.UpAnima.From - imgSize;
    this.borderAnima_Up.From = this.boardPosition.Y;
    this.currentBorderPosition.Y -= imgSize;
    this.borderAnima_Up.To = this.currentBorderPosition.Y;
    this.moveImage_Direct_Up.Begin();
    break;
   case "down":
    this.UpAnima.From =
     Convert.ToDouble(imageGrid.GetValue(Canvas.TopProperty));
    this.UpAnima.To = this.UpAnima.From + imgSize;
    this.borderAnima_Up.From = this.currentBorderPosition.Y;
    this.currentBorderPosition.Y += imgSize;
    this.borderAnima_Up.To = this.currentBorderPosition.Y;
    this.moveImage_Direct_Up.Begin();
    break;
   case "left":
    this.LeftAnima.From =
     Convert.ToDouble(imageGrid.GetValue(Canvas.LeftProperty));
    this.LeftAnima.To = this.LeftAnima.From - imgSize;
    this.borderAnima_Left.From = this.currentBorderPosition.X;
    this.currentBorderPosition.X -= imgSize;
    this.borderAnima_Left.To = this.currentBorderPosition.X;
    this.moveImage_Direct_Left.Begin();
    break;
   case "right":
    this.LeftAnima.From = Convert.ToDouble(imageGrid.GetValue(Canvas.LeftProperty));
    this.LeftAnima.To = this.LeftAnima.From + 160;
    this.borderAnima_Left.From =
      this.currentBorderPosition.X;
    this.currentBorderPosition.X += imgSize;
    this.borderAnima_Left.To =
      this.currentBorderPosition.X;
    this.moveImage_Direct_Left.Begin();
    break;
   default:
    SysMsg("default in dir");
    break;
  }
  msgPos.X = this.currentBorderPosition.X + 5;
  msgPos.Y = this.currentBorderPosition.Y + 10;


 }
 public void resetCurrentPosition(int r,int c)
 {
  this.rowIndex = r;
  this.colIndex = c;
 showInfo();
 }
 public void showInfo()
 {
  SysMsg("boardPosition(X,Y): (" + this.boardPosition.X.ToString() +
    ","+ this.boardPosition.Y.ToString() +")",
   "TopLeft: (" + imageGrid.GetValue(Canvas.TopProperty).ToString() +
   "," + imageGrid.GetValue(Canvas.LeftProperty).ToString() ,
   "RowIndex : " + this.rowIndex.ToString(),
   "ColIndex : " + this.colIndex.ToString(),
   "name : "+this.Name);
 }
}
}


4.最後是 myRecorder.cs 的內容:

using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;

namespace ImageClip_Puzzles
{
 public class myRecorder
 {
  public static readonly DependencyProperty record_ImageBox =
   DependencyProperty.RegisterAttached(
    "recordImageBox",
    typeof(imageBox),
    typeof(myRecorder),
    null);
  public static void recordImageBox(DependencyObject obj,
                   imageBox ib)
  {
   obj.SetValue(record_ImageBox, ib);
  }
  public static imageBox readImageBox(DependencyObject obj)
  {
   return (imageBox)obj.GetValue(record_ImageBox);
  }
 }
}


先前已有介紹如何在Silverlight元件裡額外加入一個屬性,「myRecorder.cs」的內容即新增的屬性的Class。

就本篇內容來說,遊戲時「圖片區塊的移動」的動作已寫好。此外為了除蟲方便,程式中加入了「SysMsg」Function,執行時我們能夠簡單看到目前圖片位置的屬性值。



執行結果

Silverlight with C#:★★★ Attached Property ★★★

『對Silverlight元件增加額外的屬性』,在許多地方都非常之好用:
1.對專案新增一個 .cs 檔案:


在此對新增的Class命名為「addedProperty」


2.addProperty.cs最初內容為:

public class addProperty // class name : the property class
{
}

請加入以下內容:

public static readonly DependencyProperty addedMsg =
    DependencyProperty.RegisterAttached(
  //Name of the property
  "addedProperty",
  //Type of the property
  typeof( bool ),
  //Type of the provider of the registered attached property
  typeof( addProperty ),
  //Callback invoked in case the property value has changed
  null );
public static readonly DependencyProperty addedMsg2 =
    DependencyProperty.RegisterAttached(
  "addedProperty2",
  typeof(string),
  typeof(addProperty),
  null);


3.接著測試程式能否加入此Attached Property,先在主要的 .xmal檔中加入以下內容:

<Grid x:Name="LayoutRoot">
<TextBlock x:Name="myText" Text="message" Loaded="onLoad"/>
</Grid>


4.加入「onLoad」function,簡單的產生一個Silverlight元件以測試結果。:

private void onLoad(object sender, RoutedEventArgs e)
{
 myText.SetValue(addProperty.addedMsg, false);
 MessageBox.Show(myText.GetValue(addProperty.addedMsg).ToString());
 myText.SetValue(addProperty.addedMsg2, "my name is Creat");
 MessageBox.Show(myText.GetValue(addProperty.addedMsg2).ToString());
}


在Attached Property裡,第一個屬性為 bool,第二個屬性為 string,程式載入後,以MessageBox顯示我們在執行中加入的Property.你甚至可以加入C#中的Object或是Silverlight元件所屬頂層Object.

2010年1月18日 星期一

Silverlight:Image U,V -- Part 3

本篇再介紹一種動態Clip Image的方法,先將以下程式碼加入UserControl:

<Grid x:Name="LayoutRoot" Background="Gray" MouseLeftButtonUp="onUp"
  VerticalAlignment="Center" HorizontalAlignment="Center">
 <Grid.RowDefinitions>
  <RowDefinition Height="5"/>
  <RowDefinition Height="300"/>
  <RowDefinition Height="5"/>
 </Grid.RowDefinitions>
 <Grid.ColumnDefinitions>
  <ColumnDefinition Width="5"/>
  <ColumnDefinition Width="300"/>
  <ColumnDefinition Width="5"/>
 </Grid.ColumnDefinitions>
 <Grid Grid.Row="1" Grid.Column="1">
  <Rectangle x:Name="posRect"/>
  <Image x:Name="img_show" Stretch="Fill"
    Source="imgs/Orz.png" Opacity="0.9">
   <Image.Clip>
    <RectangleGeometry Rect="0,0,100,100">
     <RectangleGeometry.Transform>
      <TranslateTransform X="0" Y="0" x:Name="clipPosCtrl"/>
     </RectangleGeometry.Transform>

    </RectangleGeometry>
   </Image.Clip>
  </Image>
  <Image x:Name="img_bg" Stretch="Fill"
    Source="imgs/Orz.png" Opacity="0.1"
    MouseLeftButtonDown="onDown" MouseMove="onMove"/>
 </Grid>
</Grid>


接著加入以下程式碼至 .cs中:

private void onDown(object sender, MouseButtonEventArgs e)
{
 mouseIsClick = true;
}
 bool mouseIsClick = false;
private void onUp(object sender, MouseButtonEventArgs e)
{
 mouseIsClick = false;
}
private void onMove(object sender, MouseEventArgs e)
{
 if(!mouseIsClick) return;
 clipPosCtrl.X = e.GetPosition(posRect).X - 50;
 clipPosCtrl.Y = e.GetPosition(posRect).Y - 50;
}


本篇同part 1,使用了兩個Image,上層Image做事件的觸發,下層Image顯示效果,其中主要由

 <RectangleGeometry.Transform>
  <TranslateTransform X="0" Y="0" x:Name="clipPosCtrl"/>
 </RectangleGeometry.Transform>

來控制Clip的效果。

執行結果

2010年1月17日 星期日

Silverlight:Image U,V  -- Part 2

以下Grid內容包括四個Image元件,每個Image元件都使用同一張.png圖檔,其大小為200 x 200,Image元件各別秀出100 x 100的左上、右上、左下、右下四個部份。


<Grid x:Name="LayoutRoot" Background="Gray" Width="205" Height="205">
 <Image x:Name="img_TL" Stretch="None" Source="Orz.png">
  <Image.RenderTransform>
   <TranslateTransform X="-2.5" Y="-2.5"/>
  </Image.RenderTransform>
  <Image.Clip>
  <RectangleGeometry Rect="0,0,100,100" />
  </Image.Clip>
 </Image>      
 <Image x:Name="img_TR" Stretch="None" Source="Orz.png">
  <Image.RenderTransform>
   <TranslateTransform X="2.5" Y="-2.5"/>
  </Image.RenderTransform>
  <Image.Clip>
   <RectangleGeometry Rect="100,0,100,100" />
  </Image.Clip>
 </Image>
 <Image x:Name="img_BL" Stretch="None" Source="Orz.png" >
  <Image.RenderTransform>
   <TranslateTransform X="2.5" Y="2.5"/>
  </Image.RenderTransform>
  <Image.Clip>
   <RectangleGeometry Rect="100,100,100,100" />
  </Image.Clip>
 </Image>      
 <Image x:Name="img_BR" Stretch="None" Source="Orz.png" >
  <Image.RenderTransform>
   <TranslateTransform X="-2.5" Y="2.5"/>
  </Image.RenderTransform>
  <Image.Clip>
   <RectangleGeometry Rect="0,100,100,100" />
  </Image.Clip>
 /Image>
</Grid>

執行結果

其中<RectangleGeometry Rect="startX,startY,W,H" />指定的數值內容為「X軸起始位置,Y軸起始位置,X方向顯示寬度,Y方向顯示寬度」。

Silverlight:Image U,V  -- Part 1

一般來說的「取U、V」軸,指的是說取圖片上某一範圍。例如橫軸取 0~0.5、縱軸取0~0.5,相當於顯示圖片左上角四分之一。在Silverlight上可以使用 Clip 來完成取U、V軸的動作。
另一方面,在自動調整內容大小,由最簡單的地方開始,指定某單位數量的"*"至Colunm或Row的寬高上,Silverlight內容即可依瀏覽器大小自動調整。

將以下程式碼寫入UserControl:

<Grid x:Name="LayoutRoot" Background="Gray"
  MouseLeftButtonUp="onRectUp" MouseLeave="onLeave">
 <Rectangle Stroke="Black" StrokeThickness="5"/>
 <Grid ShowGridLines="True">
  <Grid.ColumnDefinitions>
  <ColumnDefinition Width="1*"/>
  <ColumnDefinition Width="5*" MinWidth="200"/>
  <ColumnDefinition Width="1*"/>
 </Grid.ColumnDefinitions>
 <Grid.RowDefinitions>
  <RowDefinition Height="1*"/>
  <RowDefinition Height="5*" MinHeight="200"/>
  <RowDefinition Height="1*"/>
 </Grid.RowDefinitions>
 <Image x:Name="img" Stretch="Uniform" Source="Orz.png" Grid.Column="1"
   Grid.Row="1">
   <Image.Clip>
    <RectangleGeometry Rect="0,0,200,200" x:Name="clipArea"/>
   </Image.Clip>

  </Image>
 <Image x:Name="img_grid_bg" Stretch="Uniform" Opacity="0.001"
   Source="Orz.png" Grid.Column="1" Grid.Row="1"
   MouseLeftButtonDown="onDown" MouseMove="onMove" />
 </Grid>
</Grid>

接著在 .cs檔中加入EventHandler內容:

//全域--用於記錄滑鼠左鍵是否在圖片上被按下
bool mouseClickDown = false;

滑鼠左鍵在圖片上按下時:

private void onDown(object sender, MouseButtonEventArgs e)
{
 mouseClickDown = true;
 Point pos = e.GetPosition(img);
 clipArea.Rect = new Rect(0, 0, pos.X, pos.Y);
}

滑鼠在圖片上移動時:

private void onMove(object sender, MouseEventArgs e)
{
 if (!mouseClickDown) return;
 Point pos = e.GetPosition(img);
 clipArea.Rect = new Rect(0, 0, pos.X, pos.Y);
}

當滑鼠離開、滑鼠左鍵放開時:

private void onLeave(object sender, MouseEventArgs e)
{
 mouseClickDown = false;
}
private void onRectUp(object sender, MouseButtonEventArgs e)
{
 mouseClickDown = false;
}


1.其中對Image.clip元件給定一個名字(在此即clipArea),再從程式內部來對它指定新的Clip範圍,至於想要取多少的U、V,再依個人需求去做計算。
2.在.xmal中,給了兩個Image元件,其中一個主要用來觸發滑鼠事件,而另一個負責顯示U、V的效果,而U、V的範圍主要對「clipArea」指定數值來決定。

2009年12月29日 星期二

Silverlight:Web Load Media

建立一個Button物件,按下後能動態載入影片檔案。這樣的動作可以運用於「需要時才載入」,避免Silverlight的xap檔案過大導致載入時間過長。

在撰寫程式之前,請先新增一個新的專案到目前的solution中,並且將影象檔案置入該新增的專案:

新增專案至Solution,本篇將新增的專案命名為「VedioPack」

將影片檔加入專案中,在此以「_Butterfly_Small.wmv」為例:


在 .xmal檔中加入以下程式碼:

<Grid x:Name="LayoutRoot">
 <Button Width="100" Height="30" Content="load vedio" VerticalAlignment="Top"
Click="loadVedio" />
  <MediaElement Height="180" VerticalAlignment="Center" Width="240"
   d:LayoutOverrides="Width" HorizontalAlignment="Stretch"
   Volume="1" x:Name="vedio" Stretch="Uniform"/>
 <TextBlock x:Name="progressText" Text="%" Margin="-100,0"
  HorizontalAlignment="Center" VerticalAlignment="Center"/>
</Grid>


上述程式碼中,TextBlock元件將會顯示目前Media檔案的下載進度。接著在 .cs 檔案加入以下程式內容:

當按鈕被Click時:

private void loadVedio(object sender, RoutedEventArgs e)
{
  WebClient wc = new WebClient();
  wc.DownloadProgressChanged +=
  new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
  wc.OpenReadCompleted +=
  new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
  wc.OpenReadAsync(new Uri("ClientBin/VedioPack.xap", UriKind.Relative));
}

下載中,檔案下載進度的反應:

void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
  progressText.Text = e.ProgressPercentage.ToString() + "%";
}

下載檔案的結果:

void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
  if ((e.Error == null) && (e.Cancelled == false))
  {
   try
   {
    StreamResourceInfo sri =
      new StreamResourceInfo(e.Result as Stream, null);
    Uri uri =
      new Uri("_Butterfly_Small.wmv", UriKind.Relative);
    StreamResourceInfo mediaStream = Application.GetResourceStream(sri, uri);
    this.vedio.SetSource(mediaStream.Stream);
    progressText.Visibility = Visibility.Collapsed;
   }
   catch(Exception ex)
   {
    System.Windows.Browser.HtmlPage.Window.Alert(ex.Message);
   }
  }
  else
  {
   MessageBox.Show(e.Error.ToString());
  }
}


執行結果

2009年12月28日 星期一

Silverlight:下載進度

1、先在 .xaml 檔內的UserControl加入以下程式碼:

<Grid x:Name="LayoutRoot" Height="100" Width="300" Loaded="downloadObj">
 <Rectangle Fill="Black" />
 <Rectangle x:Name="bg"  Fill="Red" Height="20" Width="200"
  HorizontalAlignment="Left" Margin="50,0"/>
 <Rectangle x:Name="bar" Fill="Yellow" Height="20" Width="1"
  HorizontalAlignment="Left" Margin="50,0"/>
 <TextBlock x:Name="progressText" Text="0%" FontSize="15"
  Foreground="White" HorizontalAlignment="Center"
  VerticalAlignment="Center"/>
</Grid>


2、接著生出一個檔案,將檔案放到專案的「ClientBin/」之下(與xap檔案同資料夾,在此以SilverlightVideoPlayerClassLibrary.zip為例)
3、在.cs檔寫入以下程式碼:

private void downloadObj(object sender, RoutedEventArgs e)
{
 WebClient wc = new WebClient();
 wc.DownloadProgressChanged +=
   new DownloadProgressChangedEventHandler(wc_DownloadProgressChanged);
 wc.OpenReadCompleted += new OpenReadCompletedEventHandler(wc_OpenReadCompleted);
 wc.OpenReadAsync(new Uri("SilverlightVideoPlayerClassLibrary.zip",
           UriKind.Relative));
}

void wc_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
 if (e.Error == null)
 {

 }
 else
 {
  MessageBox.Show("error : " + e.Error.ToString());
 }
}

void wc_DownloadProgressChanged(object sender, DownloadProgressChangedEventArgs e)
{
 bar.Width = (double) e.ProgressPercentage * 2;
 progressText.Text = e.ProgressPercentage.ToString() + "%";
}


progressText為TextBlock元件,在此利用WebClient做到檔案下載的動作,以event handler取得下載進度,反應於 wc_DownloadProgresshanged中。

2009年12月23日 星期三

Silverlight:物件化管理----Add Reference

1、建立新的Sliverlight專案:


2、在相同的solution下,額外新增一個專案(Silverlight Class Library):


3、Project add reference,對主專案按下滑鼠右鍵,選擇「Add reference」,reference的對象則是先前新增的Project:

在主要專案找到「Reference」,會看見額外新增的專案已被加入


4、在額外新增的專案中加入xmal檔,並建立內容:


選擇「Silverlight User Control」並指定xmal檔名


新增的專案中,其新增的xmal檔內容如下

<UserControl x:Class="LoadedXAML.execAnimation"
 xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 Width="400" Height="300">
  <Grid x:Name="LayoutRoot" Loaded="whenLoaded">
   <Grid.Resources>
    <Storyboard x:Name="anima">
     <DoubleAnimation Storyboard.TargetName="path1"
       Storyboard.TargetProperty=
       "(Rectangle.RenderTransform).X"
       From="0" To="300" AutoReverse="true"
       BeginTime="0:0:0"
       Duration="0:0:2" RepeatBehavior="Forever"/>
    </Storyboard>
   </Grid.Resources>
  <Grid>
   <Rectangle x:Name="path1" Opacity=".65" Fill="orange"
    Height="100" Width="100" RadiusX="10" RadiusY="10" >
    <Rectangle.RenderTransform>
     <TranslateTransform X="0"/>
    </Rectangle.RenderTransform>
   </Rectangle>
  </Grid>
 </Grid>
</UserControl>

新增的xmal檔其.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 LoadedXAML
{
public partial class execAnimation : UserControl
{
public execAnimation()
{
InitializeComponent();
}

private void whenLoaded(object sender, RoutedEventArgs e)
{
anima.Begin();
}

}
}




5、主xmal檔請加入一個Button元件:

<Button x:Name="Button_LOAD" Width="100" Height="60"
  Content="Load" Click="doLoad" />

其.cs內容需加入「doLoad」function,程式內容如下:

private void doLoad(object sender, RoutedEventArgs e)
{
 UserControl myCtrl = new LoadedXAML.execAnimation();
 Grid myGrid = (Grid) this.FindName("LayoutRoot");
 myGrid.Children.Add(myCtrl);
}


程式的兩個Project已建立連結,主Project在按下Button後將能夠取得先前新增的xmal檔內容。

2009年12月15日 星期二

Silverlight:Set Color、Set Margain

建立一個名為「newRect」的Rectangle元件,在cs檔中指定Rectangle裡 Fill的顏色值如下:

 Color newColor = Color.FromArgb(255, 0xEE, 0xEE, 0xEE);
 newRect.Fill = new SolidColorBrush(newColor);

或者在new一個Rectangle時你也可以這樣做:

 Color newColor = Color.FromArgb(255, 0xEE, 0xEE, 0xEE);
Rectange rect =
  new Rectange() { Fill = new SolidColorBrush(newColor)};


指定Margin上、下、左、右的方式如下:

 Thickness newTk = new Thickness();
 newTk.Top = (double)5;
 newTk.Left = (double)5;
 newTk.Right = (double)5;
 newTk.Bottom = (double)5;
 newRect.SetValue(Rectangle.MarginProperty, newTk);

SilverLight:指定Grid某一欄位的寬、高

1、在xmal檔中,對目標欄位設定「x:name」,例如:

<Grid x:Name="PS_Container" Visibility="Visible" Height="500">
 <Grid.ColumnDefinitions>
  <ColumnDefinition x:Name="container_Grid_Width1" Width="1*"/>
  <ColumnDefinition x:Name="container_Grid_Width2" Width="4*"/>
  <ColumnDefinition x:Name="container_Grid_Width3" Width="6*"/>
 </Grid.ColumnDefinitions>
</Grid>

在cs檔中,指定寬度的方式(以下分別指定Colunm1、Colunm2、Colunm3):

 GridLength gl = new GridLength(82);
 container_Grid_Width1.Width = gl;
 gl = new GridLength(328);
 container_Grid_Width2.Width = gl;
 gl = new GridLength(Application.Current.Host.Content.ActualWidth - 410);
 container_Grid_Width3.Width = gl;


以上將欄位寬度分成82、328、(410-328-82)等大小,其中Application.Current.Host.Content.ActualWidth能夠取得目前頁面的實際寬度。

Silverlight:讓Button能夠使用 MouseLeftButtonDown & Up

Silverlight在使用Button時,只有「Click」事件能夠產生動作,而「MouseLeftButtonDown」及「MouseLeftButtonUp」…等多個Mouse動作都無作用。
在某些狀況下我們可能需要「MouseDown」及「MouseUp」配合使用,針對這項需求,可使用以下方式解決--

在此以RepeatButton舉例:
對xmal檔中的button物件指定「Click」、「MouseLeftButtonDown」、「MouseLeftButtonUp」等事件,並設定「ClickMode」為「Hover」:

<RepeatButton  Opacity="0.01" Width="24" Height="26" Interval="100"
  Margin="-8" ClickMode="Hover"
  Click="on_tomorrow" MouseLeftButtonDown="on_tomorrow_down"
  MouseLeftButtonUp="on_tomorrow_up"/>

在cs檔中寫前對應的function。將「ClickMode」設定為「Hover」時,只要mouse置於button上就會觸發Click事件,mouse置於button上時,以一個bool變數去判斷mouse是不是Down的狀態,即可使用MouseLeftButtonDown及MouseLeftButtonUp的功能:

 bool butmDown = false;
 private void on_tomorrow(object sender, RoutedEventArgs e)
 {
  if (!butmDown) return;
  …//when mouse down, do something on this code..
  …
 }
 private void on_tomorrow_down(object sender, MouseButtonEventArgs e)
 {
  butmDown = true;
 }
 private void on_tomorrow_up(object sender, MouseButtonEventArgs e)
 {
  MessageBox.Show("release mouse");
  butmDown = false;
 }

2009年12月7日 星期一

Silverlight: Cookie的使用

首先需要引用…

using System.Windows.Browser;


寫入cookie:以下內容會將「Key=Nothing」寫入cookie中

DateTime expiration = DateTime.UtcNow + TimeSpan.FromDays(2000);
string cookie = String.Format("{0}={1};expires={2}",
      "Key", "Nothing", expiration.ToString("R"));
HtmlPage.Document.SetProperty("cookie", cookie);


刪除cookie內容值:以下內容會將「Key」值移除
 DateTime expireDate = DateTime.Now - TimeSpan.FromDays(1);
 string expires = ";expires=" + expireDate.ToString("R");
 string cookie = "Key=" + expires;
 HtmlPage.Document.SetProperty("cookie", cookie);


讀取cookie內容值:以下將會找出「Key」的內容值,並以MessageBox提示
 String[] cookies = HtmlPage.Document.Cookies.Split(';');
 string key = "Key=";
 foreach (string s in cookies)
 {
  string ck = s.Trim();
  if (ck.StartsWith(key, StringComparison.OrdinalIgnoreCase))
  {
   string[] vals = ck.Split('=');
   MessageBox.Show(vals[1]);
  }
 }

2009年12月3日 星期四

Silverlight、C#:Post in HttpWebRequest

以下主要在從事Silverlight做Web Request,以Post對Server要求資料時用上:

 WebClient wc_DoLogin = new WebClient();
wc_DoLogin.UploadStringCompleted += new
   UploadStringCompletedEventHandler(wc_DoLogin_UploadStringCompleted);
 wc_DoLogin.Headers["content-type"]
   = "application/x-www-form-urlencoded";
 wc_DoLogin.UploadStringAsync(
  new Uri(Url, UriKind.Absolute),
  "POST",
  "欄位1=欄位值&欄位2=欄位值2");

Server回應將會在wc_DoLogin_UploadStringCompleted被接收:

void wc_DoLogin_UploadStringCompleted
(object sender, UploadStringCompletedEventArgs e)
{
MessageBox.Show("result is : " + e.Result);
}

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,變換圖片的動作才能夠正常執行。