안녕하세요? 맨날맑음입니다.

일반적으로 실버라이트 프로젝트를 생성하면 위와 같이 두 개의 프로젝트가 생성됩니다. 하나는 실버라이트 프로젝트이고, 하나는 [프로젝트명].[Web]이 붙은 프로젝트인데요. Web이 붙은 프로젝트를 살펴보면 ASP.NET 프로젝트 인 것을 알 수 있습니다. 웹 프로젝트의 .aspx(웹폼)의 소스를 살펴보면 Active-X 처럼 object 태그를 이용하여 실버라이트를 웹 페이지에 로딩하는 것을 볼 수 있습니다.

이와 같이 실버라이트는 웹에서 동작하는 응용프로그램이고, 프로젝트의 상황에 따라 전체 페이지를 실버라이트로 만들 수도 있지만, ASP.NET으로 웹 페이지를 구성하고, 비주얼한 영역만 실버라이트로 제작하는 것이 일반적입니다.

 

이렇게 실버라이트를 웹 페이지의 특정 영역에 올려놓을 경우 실버라이트와 HTML간의 정보교환이라는 이슈가 생기기 마련인데요. 이번 포스팅에서는 실버라이트 <-> HTML 간의 엑세스 방법에 대해 알아보려 합니다.

 

#1. 실버라이트에서 HTML 접근

우선 실버라이트에서 HTML의 요소에 접근하는 방법을 알아 보기 위해서, 간단하게 HTML과 실버라이트에 컨트롤을 배치합니다.

위쪽의 흰색 배경이 HTML영역이고 아래쪽에 푸른 배경이 실버라이트 영역입니다. 위쪽 HTML영역의 글을 텍스트박스에 입력하고, Silverlight 영역의 버튼을 누르면 HTML의 정보를 실버라이트 텍스트박스에 넣는 시나리오 입니다.

 

<UserControl x:Class="HTMLBridge.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"
    >

    <StackPanel x:Name="LayoutRoot" Background="Azure">
        <TextBlock FontSize="14" Text="Silverlight 
영역"/>

        <StackPanel Orientation="Horizontal">
            <TextBox x:Name="txtHTML" Width="400" /> 
            <Button x:Name="btnGetHTML" 
                   Content="
버튼을 누르면 HTML 접근" 
                   Margin="10,0,0,0" 
                   Click="btnGetHTML_Click" />
        </StackPanel>
    </StackPanel>
</UserControl>

-MainPage.xaml-

 public partial class MainPage : UserControl
 {
     public MainPage()
        {
            InitializeComponent();            
        }
     private void btnGetHTML_Click(object sender, RoutedEventArgs e)
     {
         HtmlDocument htmlDocument = HtmlPage.Document;
         HtmlElement htmlElement = htmlDocument.GetElementById("htmlInputBox");
         string text = htmlElement.GetAttribute("value");

         if(text!=null)
         {
             this.txtHTML.Text = text;
         }
     }

-MainPage.xaml.cs-

<form id="form1" runat="server" style="height:100%">
<h2>HTML
영역</h2>
텍스트
 입력 : <input type="text" id="htmlInputBox" style="width:400px;" /><hr />
<div id="silverlightControlHost">
    <object data="data:application/x-silverlight-2," type="application/x-silverlight-2" width="100%" height="100%">

……

-HTMLBridgeTestPage.aspx-

XAML에는 컨트롤의 배치가 선언 되어있고 btnGetHTML이라는 이름을 가진 버튼의 Click이벤트 핸들러가 정의되어 있습니다.비하인드 코드가 중요한데요. HtmlDocument 객체를 가져와서 GetElementById 메서드를 이용하여 HTML의 텍스트박스를 얻어 올 수 있습니다. HtmlElement 객체의 GetAttribute는 HTML요소의 속성값을 읽어 올 수 있습니다. 또한 SetPropertySetAttribute 메서드를 이용하여 값을 설정 할 수 있습니다.

실행시켜 보면 위와 같은 결과를 얻을 수 있습니다.

 

또한 HTML의 이벤트도 실버라이트에서 컨트롤 할 수 있는데요. AttachEvent메서드를 이용하면 됩니다.

public MainPage()
{
    InitializeComponent();
    HtmlDocument htmlDocument = HtmlPage.Document;
    HtmlElement htmlElement = htmlDocument.GetElementById("htmlInputBox");
    htmlElement.AttachEvent("onkeyup"new EventHandler(this.OnChange));
}
private void OnChange(object sender, EventArgs e) {     HtmlDocument htmlDocument = HtmlPage.Document;     HtmlElement htmlElement = htmlDocument.GetElementById("htmlInputBox");
   string text = htmlElement.GetAttribute("value");



   if (text != null)     {         this.txtHTML.Text = text;     } }
private void btnGetHTML_Click(object sender, RoutedEventArgs e)
{
    OnChange(nullnull);
}

- MainPage.xaml.cs -

테스트를 위해 AttachEvent 메서드를 이용하여, 생성자에 HTML의 텍스트 박스의 KeyUp 이벤트를 설정하였고, 이벤트 핸들러에서는 요소에서 가져온 텍스트를 실버라이트의 텍스트 박스에 설정합니다.

실행결과 HTML 텍스트박스의 글자가 바뀔 때 마다 실버라이트의 텍스트박스에 나타납니다.

#2. HTML에서 실버라이트 접근

HTML에서 실버라이트에 접근하는 시나리오를 위해 위와 같이 기존 .aspx에 버튼을 추가하고, 실버라이트 object요소에 id값을 추가합니다. 그리고 버튼의 클릭 속성에 자바스크립트 함수를 넣어줍니다.

<h2>HTML영역</h2>
    텍스트 입력 : <input type="text" id="htmlInputBox"   style="width:300px;" /> 	
<input type="button" id="htmlButton" onclick="CallSilverlight()" 
       value="버튼을 누르면 실버라이트에 접근" /><hr />
<div id="silverlightControlHost">
   <object id="ObjSilverlight" data="data:application/x-silverlight-2," 
            type="application/x-silverlight-2"
............

- HTMLBridgeTestPage.aspx -

실버라이트에 접근하려면 자바스크립트를 사용해야 하는데요. 버튼을 누르면 실버라이트의 텍스트박스에서 값을 가져와 HTML의 텍스트박스에 집어 넣도록 하겟습니다. 아래와 같이 자바스크립트를 <head>태그 안에 추가합니다.

<script type="text/javascript">
        function CallSilverlight() {
            var ObjSilverlight = document.getElementById("ObjSilverlight");
            var text = ObjSilverlight.Content.REG_SILVERLIGHT.SilverlightMethod();
            document.getElementById("htmlInputBox").value = text;
        }
    </script>

- HTMLBridgeTestPage.aspx –

자바스크립트를 살펴보면 document객체의 getElementById 함수에 실버라이트 Object태그의 id값을 넣어 실버라이트 객체를 얻어옵니다. 그 다음줄에서 ObjSilverlight.Content.REG_SILVERLIGHT.SilverlightMethod();와 같은 코드가 보이는데요, 이것이 핵심입니다.

 

자바스크립트를 통해 실버라이트에 접근하기 위해서는 RegisterSCriptableObject아래와 같이 객체를 등록 하여야 합니다. 객체를 등록하기 위해서는 객체에 [ScriptableMember]가 있어야 하고, 이 속성이 붙은 메서드는 자바스크립트에 노출됩니다.

 public MainPage()
 {
     InitializeComponent();
     ……
     HtmlPage.RegisterScriptableObject("REG_SILVERLIGHT"this);
 }
[ScriptableMember]  public string SilverlightMethod()  {
     return this.txtHTML.Text;  }

-MainPage.xaml.cs-

즉 위의 자바스크립트의 코드는 등록 된 실버라이트 객체의 ScriptableMemeber를 호출하는 코드입니다.

테스트를 해보니 HTML버튼을 누르면 자바스크립트가 호출되어, 실버라이트의 메서드를 호출하는 것을 알 수 있습니다.

 

실버라이트를 처음으로 접할 때 프로젝트를 생성해 보셨을 것입니다. 프로젝트의 구조를 살펴보고, ASP.NET이나 HTML위에 실버라이트가 Object태그로 추가되는 것을 보고, 한번쯤 둘간의 상호작용을 어떻게 할지에 대해 궁금하셨을 것입니다. 오늘은 가장 기본이 되는 실버라이트와 HTML간의 엑세스 방법에 대해 알아 보았습니다. 이 방법은 ASP.NET과 자바스크립트 기술을 이용하는 것이고 이것을 이용하여 실버라이트가 addOn된 멋진 페이지를 작성 할 수 있습니다.

Posted by 맨날맑음
,

정말 오랜만의 포스팅입니다. (이제부터 예의바른 블로거가 되기위해 존댓말로 포스팅하기로 했습니다)
핑계없는 무덤은 없다지만 핑계를 대자면,, 지금 진행하는 프로젝트에 쫒겨 시간이 없었다고,,라고 하고싶지만
게을러서 입니다. 게으른 블로거되서는 안되는데 큰일입니다;;

아무튼 이번 포스트에서는 FindName(); 메서드에 대해 알아보려 합니다.
여러분은 Silverlight App를 개발하면서 FindName()을 사용하십니까?
사실 일찌감치 FindName() 메서드의 존재와 역할을 알았지만 필요없는 메소드라 생각하여 잊어버렸습니다.
사용하지 않았죠...;

FindName();
System.Windows.Documents 네임스페이스의 Inline 클래스의 멤버매서드
역  할 : 개체의 x:Name 또는 Name 특성 값을 참조하여 Silverlight 개체를 가져온다.
인자값 : string
리턴형 : object


Page에 Rectangle이 있고 x:Name이 MyRect라고 할때  Page.xaml.cs에서는 MyRect라는 x:Name만으로도
Rectangle객체의 컨트롤이 가능합니다.
 예를들어 이런것이죠  >>   this.MyRect.Width = 100;
x:Name만 알아도 충분히 컨트롤이 가능한데 굳이 아래와 같이 복잡하게 객체를 알아올 필요성을 못느낀것이죠.
object o = this.FindName("MyRect");
Rectangle myrect = o as Rectangle;
if (myrect != null)
{
     // to do..
 }


그럼 FindName을 어떤때 써야될까요? 저는 이런 경우에 활용해 보았습니다.
를들어 보자면 로그인하는 시나리오가 적당하겠네요.

Page에서 로그인 버튼을 누르면 로그인 컨트롤(UserControl로 만들어진)이 새로 뜨고 사용자는 ID와 PW를 입력하여 로그인 하게 됩니다. 로그인 된다면 Page의 TextBlock에 사용자가 입력한 ID가 나타나게 한다고 합시다.

Page는 로그인 컨트롤을 알고 있지만(로그인 컨트롤의 Public한 속성에 접근할수 있지만) 로그인 컨트롤은
Page를 알지 못합니다. 물론 로그인컨트롤의 비하인드코드에서 this.parent를 이용하여 부모는 알수있을 겁니다.
하지만 (Page)this.parent;처럼 Page클래스로 캐스팅하면 컴파일 타임에 오류를 일으킵니다. 캐스팅 할수가 없죠.

저는 이걸 해결하기 위해 로그인 컨트롤의 생성자를 오버로딩하여 Page의 TextBlock 컨트롤을 인자로 넘겨주는 방법으로 코딩해왔습니다.

하지만 FindName을 이용하여 해결 할 수도 있습니다. this.parent를 찾아서 Panel로 캐스팅후
FindName() 메서드를 호출하여 TextBlock 개체를 찾으면 되는것이죠!
굳이 생성자에 넘기고 자시고 할 필요가 없습니다.

자.. 방법을 알았으니 간단한 스텁 프로그램을 작성해 보도록 하겠습니다.(앞에서 말한 로그인 예제로 하죠)

1. 우선 실버라이트 응용프로그램을 생성하구요 (프로젝트명을 FindNameTesting으로 했습니다.)
2. Page.xaml블랜드에서 열어 디자인 합니다. 간단하게 TextBlock(x:Name = "txtUserID")
   버튼(x:Name = "btnLog")을 하나 넣었습니다.
   버튼은 Grid로 만들었구요.. Grid안에 Rectangle 객체와 TextBlock(x:Name = "txtLogMSG")를 넣었습니다.


2. Silverlight 사용자정의 컨트롤(UserControl)을 추가 합니다.(LogInControl이라 명명 했습니다.)
    LogInControl을 블랜드에서 열어 디자인해 줍니다. 저는 아래와 같이 했구요;

  그냥 간단하게 ID를 입력받는 TextBox(x:Name = "txtInputID") 와  PW를 입력받는 PasswordBox(x:Name = "txtInputPW")를 추가하고 버튼(x:Name = "btnLogIn")도 하나 놓습니다.

3. 이제 LogInControl의 비하인드 코드(LogInControl.xaml.cs)로 가서 이벤트 처리 메서드를 작성합니다.
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;

namespace FindNameTesting
{
    public partial class LogInControl : UserControl
    {
        public LogInControl()
        {
            InitializeComponent();
            this.Loaded += new RoutedEventHandler(LogInControl_Loaded);
        }

        void LogInControl_Loaded(object sender, RoutedEventArgs e)
        {
            btnLogIn.MouseLeftButtonDown += new MouseButtonEventHandler(btnLogIn_MouseLeftButtonDown);
        }

        void btnLogIn_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (!CheckedIdAndPw())            
            {
                Storyboard1.Begin();
                return;
            }
            object o = ((Panel)this.Parent).FindName("txtUserID");
            TextBlock txtuserid = o as TextBlock;
            if (txtuserid != null)
            {
                txtuserid.Text = string.Format("{0}님 환영합니다^^",txtInputID.Text);
            }

            object o2 = ((Panel)this.Parent).FindName("txtLogMSG");
            TextBlock txtlogmsg = o2 as TextBlock;
            if (txtlogmsg != null)
            {
                txtlogmsg.Text = "LogOut";
            }
            ((Panel)this.Parent).Children.Remove(this);            
        }

        private bool CheckedIdAndPw()
        {
            if (txtInputID.Text != "맨날맑음" || txtInputPW.Password != "silverlight")
            {
                return false;
            }
            return true;
        }
    }
}

    로그인 버튼을 누르면 LoginControl의 부모인 Page에서 txtUserID개체를 찾아 입력받은 ID를 대입했구요
    같은방법으로 Page에 있는 로그버튼의 TextBlock을 찾아 LogIn이라는 글자도 LogOut으로 변경하였습니다.
    그후에 생성된 LoginControl을 Page에서 제거 하였습니다.

4. 마지막으로 Page.xaml.cs를 작성합니다.
using System.Windows.Controls;
using System.Windows.Input;

namespace FindNameTesting
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            this.btnLog.MouseLeftButtonDown += new MouseButtonEventHandler(btnLog_MouseLeftButtonDown);
        }

        void btnLog_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (txtLogMSG.Text == "LogIn")
            {
                this.LayoutRoot.Children.Add(new LogInControl());
            }
            else
            {
                txtLogMSG.Text = "LogIn";
                txtUserID.Text = "안녕하세요? 로그인하세요";
            }
        }
    }
}

매우 간단합니다. 버튼을 누르게 되면 로그인컨트롤(LogINControl)을 생성합니다자..이제 로그인하게되면
로그인한 화면이 Page의 TextBox를 갱신시킬까요?... 네~잘됩니다
아래는 지금 만든 예제를 조금 수정한 것입니다~(ID : 맨날맑음, PW : silverlight) 테스트 해보시면 잘되는걸 볼 수있습니다.



이외에도 WPF에서는 FindName() 메서드로 개체를 불러와야만 개체의 컨트롤이 가능합니다~
이 방법을 사용하면 부모든 부모의 부모든 상관없이 type만 알고있다면 모든 컨트롤을 제어할수 있겠고,
public한 속성들도 제어할 수 있습니다!
다른 쓰임새가 많겠지만 아직 실력이 미천하여 이럴때 사용하고 있습니다;
다른곳에 활용하신분들은 피드백이나 댓글 부탁드립니다.
Posted by 맨날맑음
,
티스토리 블로그에 실버라이트 올리기!

실버라이트를 빌드하면  Debug 폴더나 ClientBin 폴더내에 xap 파일이 생성된다;
정확히는 모르겠으나 여기저기 웹서핑과 MSDN 참조 결과 xap 파일만 있으면 실버라이트 결과물을
HTML에 <Object> 태그로 집어 넣을 수 있겠다 싶어서 티스토리에 올릴려고 무진장 많이 노력했지만
계속 흰화면만 뜨는것이었다;
<object  data="data:application/x-silverlight-2," type="application/x-silverlight-2">
    <param name="source" value="xap 파일의 경로"/>
  
    <!-- Display installation image. -->
    <a href="
http://go.microsoft.com/fwlink/?LinkID=124807"
        style="text-decoration: none;">
        <img src="
http://go.microsoft.com/fwlink/?LinkId=108181"
            alt="Get Microsoft Silverlight"
            style="border-style: none"/>
    </a>
</object>  

주석아래 <a href>와 <img> 태그는 실버라이트 런타임이 설치되지 않았을때 나올 다운로드 이미지이다!
HTML의 <BODY> 태그내에 저 구문을 넣어주면 된다고 MSDN에는 나와있는데;;
이게 로컬에 xap 파일이 있는경우에는 잘되지만 다른곳에 있으면 잘안되서 고민한 끝에;

약간 편법으로 저 HTML 파일과 xap 파일을 웹서버에 함게 업로드하고
HTML 문법인 IFRAME을 사용하여 저 HTML을 띄우는 방법으로 했더니만 아주 잘됬다!!
<IFRAME  src="HTML의 경로">
</IFRAME>

성공(?)기념 !! Silverlight DeepZoom Sample!!(사실 LiveDK 블로그에 있는 딥줌이 부러워서'')
 마우스로 클릭하거나 휠을 돌려보세요


PS. 먼가 다른 방법을 아시는분은 댓글이나 피드백을... 부탁드려요'' 굽신굽신

Posted by 맨날맑음
,
실버라이트로 준비하고 있는 프로젝트가 막바지 인데 아직도 갈길이 멀다;;
옆자리 태욱이가 -_-; 물어본게 있었지만 실버라이트에선 안된다고 우긴게 부끄럽게도;
담배피고왔더니 "병재님" (특별히 님을 붙임!)의 도움으로 어떻게 하는지 알아버렸다


하고 싶었던 기능은 특정한 영역안에서만 표시되는 일종의 플래쉬의 '마스크' 같은 효과였는데
패널들의 Clip 기능을 사용하면 되는것이었다;;

우리조의 히어로 동규씨의 도움으로 블로그에 실버라이트를 넣는 방법을 배웠기때문에''
(이것에대해선 다음에 포스팅 할께요)
일단 구현하려는 예제부터 보도록 하겠다;

이렇게 하려고 하는데;  문제는 저 안쪽에 움직이고 있는 사각형이 영역 밖으로 삐져나오는;
이런결과 밖에 할수 없었다;; 적어도 Clip을 알기전엔..


이제 삐져나오지 않는법을 설명하자면
보이고싶은 영역(Grid)에 Clip을 설정하면 된다;
<Grid Margin="0,0,0,0" Width="100" Height="100" x:Name="MaskGrid">
            <Grid.Clip>
                <RectangleGeometry Rect="0,0,100,100"/>
            </Grid.Clip>
</Grid>

이렇게 <Grid.Clip>
                <
RectangleGeometry Rect
="0,0,100,100"/>
            </
Grid.Clip
>
을 지정해주면 100 * 100 사이즈의 Rect 영역 안에서만 그리드의 자식 객체들이 보이게 된다!!!
Rect 뿐 아니라 Ellipse, Line, Path 등도 가능하니 응용하면 멋진 효과를 낼수 있을 듯 하다!
Posted by 맨날맑음
,

실버라이트에는 각 컨트롤에 Style을 적용시켜 사용할수 있다''

스타일은 HTML의 CSS의 개념과 흡사한 개념이며;
실버라이트에서는 스타일과 더불어 템플릿이라는 개념을 제공하여 사용자가 컨트롤을 쉽게
만들수 있게 하였다;

스타일은 쉽게 말해 컨트롤들의 속성을 미리 정의해 놓고 나중에 불러서 쓰는것이고
템플릿은 컨트롤내의 모양, 형태, 이벤트발생시 처리로직이라던지 그런것을 바꿔줄수 있는것이다;

이번 포스트의 목적인 스타일을 알아보자면
스타일의 사용하는 이유는 재사용성이라는 측면이 가장 큰것 같고, 속성의 변경시 쉽게 정의 부분만
변경하게되면 그 스타일을 적용받는 모든 컨트롤의 속성이 변경되기 때문에 간단하게 유지보수 할수 있게 된다;
그리고 마지막 장점이라면 코드가 간결해진다 이정도로 생각해 볼수 있지 않을까;;


그럼 스타일을 어떻게 정의하고 어떻게 적용시키는지 알아보겠다;

>> 실버라이트 응용프로그램 프로젝트를 생성하여 page.xaml에 아래와 같이
    버튼 9개를 넣어 보았다;



<Button  Content="버튼1" Grid.Row="0" Grid.Column="0"/>
<Button  Content="버튼2" Grid.Row="0" Grid.Column="1"/>
<Button  Content="버튼3" Grid.Row="0" Grid.Column="3"/>
<Button  Content="버튼4" Grid.Row="1" Grid.Column="0"/>
<Button  Content="버튼5" Grid.Row="1" Grid.Column="1"/>
<ButtoContent="버튼6" Grid.Row="1" Grid.Column="2"/>
<Button  Content="버튼7" Grid.Row="2" Grid.Column="0"/>
<Button  Content="버튼8" Grid.Row="2" Grid.Column="1"/>
<Button  Content="버튼9" Grid.Row="2" Grid.Column="2"/>


>> 스타일을 정의 하기 위해 app.xaml 코드로 가서

     <Application.Resources> 태그속에 스타일을 적용한다!
 <Style TargetType="Button" x:Key="MyButtonStyle">
       <Setter Property="FontFamily" Value="Gungsuh"/>
       <Setter Property="FontSize" Value="20"/>
       <Setter Property="Foreground" Value="#FFFF0000"/>           
</Style>
       TargetType은 변경할 컨트롤의 타입명 x:Key는 나중에 불러다 쓸 스타일의 이름이다;
         Setter 어트리뷰트 값으로 Property
에는 변경하고 싶은 속성을  Value에는  값을 입력하면 된다;
         간단하게 나는 폰트를 궁서체로 글씨 크기는 20 폰트 색상을 빨강으로 입력해 보았다;  쉽다;


>>이제 page.xaml에 있는 버튼들에 속성을 줘보자;

<
Button  Content="버튼1" Grid.Row="0" Grid.Column="0"
Style="{StaticResource MyButtonStyle}"/>


Style
="{StaticResource MyButtonStyle} 간단하게 이 구문만 추가하면 버튼에 스타일이 입혀지게 된다!
여기서 StaticResource 옆에 자신이 정의한 스타일의 Key를 넣으면 된다;
버튼이 궁서체 20pt 빨간색으로 바뀐것을 볼수있다



버튼 색상을 파란색으로 바꾸어야할때..

스타일을 쓰지 않은 코드에서는 9개에 속성값을 일일이 변경해야하는 번거로움이 있겠지만
스타일을 사용한 코드는 app.xaml에있는 스타일의 정의만 살짝 변경해주면 쉽게 컨트롤의
속성을 변경 할 수있다



Posted by 맨날맑음
,

실버라이트 개발시에 공식사이트인 http://www.silverlight.net/getstarted 에 있는 내용 많이 참고 하실 텐데요. 각각 해당하는 링크들이 한글판이 설치되신 분들은 경우는 따로 선택을 하셔야 되는 번거로움도 있는 것 같고 해서 실버라이트2 설치 프로그램의 한글과 관련된 링크를 모아 보았습니다.

기존의 영문판이 편하신 분들도 있겠지만, 실버라이트를 처음 시작하시는 분이라면 조금 더 친절한 한글판을 사용하시는 것도 좋을 것 같다는 생각이 들고, 게다가 현재 실버라이트 2 개발문서까지 모두 한글화 된 시점이라...
아래의 1, 2, 3 번 까지 하시면 본인의 PC를 실버라이트 2 개발 환경으로 만드실 수 있습니다.

Silverlight 배너


1. 개발툴 설치(Profession를 설치하시려면 처음 두 개, Express를 설치하시려면 세 번째 링크만)

한글 Visual Studio 2008 Professional Edition 평가판(90일) 다운로드 (ISO형태라서 가상 이미지 툴 필요)

한글 Visual Studio 2008 서비스팩1(설치 관리자)

한글 Visual Web Developer 2008 Express Edition with SP1 다운로드 및 설치(서비스 팩이 합쳐진 버전)


2. 실버라이트 툴 설치(실버라이트 개발자용 Runtime, SDK, VS Tool 합쳐짐)


한글 Visual Studio 2008 SP1용 Microsoft® Silverlight™ Tools(Runtime, SDK, VS용 Tool 포함)


3. 디자인 툴 설치(Visual Studio와 연동할 수 있는 Expression Blend)

한글 Microsoft Expression Blend™ 2 평가판(30일)

한글 Microsoft Expression Blend™ 2 서비스 팩 1(Blend 2와 합쳐진 것은 없음)


4. 추가 다운로드

Deep Zoom Composer(영문) - 버전업이 되면 링크가 달라질 수 도 있음.

Silverlight Toolkit(영문) - 추가 컨트롤(차트, 그래프, 자동완성 등)

Microsoft Silverlight 2 개발자용 런타임 - SL2 런타임만 지웠다가 다시 깔때 필요(공도님 링크참고)

한글 Microsoft® Silverlight™ 2 소프트웨어 개발 키트 - 실버라이트 2 한글 도움말 파일

Silverlight - MSDN Library(한글문서) - 온라인으로 실버라이트 한글 도움말을 보시려면...


출처 : UXCommando! :: Silverlight blog

Posted by 맨날맑음
,


어플레케이션을 개발 하다 보면 종종 멀티키(Ctrl + c , Ctrl + v등) 입력을 지원해야 하는 경우가 있다''

실버라이트에서는 기본적으로 두가지 키보드관련 이벤트가 지원 되는데
KeyDown과 KeyUp이다''

void KeyDown(object sender, KeyEventArgs e);
이벤트처리기에서 두번째 매개변수의 KeyEventArgs ee.Key를 이용하면 사용자가 누른 키
알아낼수 있고 object sender는 어떤 컨트롤에서 일어난 키보드 이벤트인지 알아낼수 있다''

☞ Ctrl + C 조합 판별하는 로직!

void KeyDown(object sender, KeyEventArgs e)
{
       if (e.Key == Key.C && Keyboard.Modifiers == ModifierKeys.Control)
       {
               //to do..
       }
}


 

Posted by 맨날맑음
,

Silverlight에서 컨트롤을 드래그 하는 방법을 알아보자!
얼마전에 컨트롤을 드래그 하는것을 만들다가 Silverlight의 좌표 체계(?)인
Margin 방식이 좀 낯설어서 생각보다 오래 테스트를 하여 구현 했기 때문에
드래그하는 방법을 차근차근 알아보려한다. 

구현할 프로그램

 Grid 안에 담긴 컨트롤을 마우스로 드래그 되야함.
   유의사항
       드래그 될때 마우스로 잡은 곳이 변경 되어서는 안되며! 빠르게 움직여도  컨트롤을 놓쳐서는 안된다!

프로젝트 생성 (MyDrag)



Microsoft Expression Blend툴을 이용한 간단한 컨트롤 디자인

간단한 메모 기능이 있는 웹젯같은 형태로 만들기 위해 TextBox를 배치햇고 상단에는 Drag를 위한
DragPanel이라는 Grid 배치
여기서 컨트롤의 Margin의 right botton 부분을 0으로 고정한다;

 
비하인드 코드( page.xaml.cs)로 가서 DragPanel의 마우스 이벤트를 등록한다
Class의 멤버 변수로 이전 마우스의 좌표를 저장하기 위한 Point beforePositon; 변수를 선언한다

Point beforePositon;

void DragPanel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
            DragPanel.MouseMove -= new MouseEventHandler(DragPanel_MouseMove);
}

void DragPanel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
            DragPanel.MouseMove += new MouseEventHandler(DragPanel_MouseMove);
}

void DragPanel_MouseMove(object sender, MouseEventArgs e)
{
           
}


여기서 MouseLeftButtonDown이벤트 발생후에만 Drag를 할수있으므로 MouseLeftButtonDown이벤트 처리기에
DragPanel.MouseMove += new MouseEventHandler(DragPanel_MouseMove);
이벤트를 등록하고 MouseLeftButtonUp 이벤트 처리기에서 마우스 Move 이벤트를 해지한다!


이제 마우스 MouseLeftButtonUp 이벤트 처리기부터 차근차근 코딩 해보자;
일단 마우스가 클릭되면 컨트롤 밖으로 마우스가 벗어나더라도 마우스 이벤트를 받을수 있어야
빠르게 드레그해도 드레그가 되기 때문에 DragPanel.CaptureMouse(); 를 호출한다

드레그를 시작한 마우스 좌표를 저장하기 위해 미리 선언해둔 beforePosition 변수에 현재 좌표를 저장한다
beforePositon = e.GetPosition(LayoutRoot);
void DragPanel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
            DragPanel.CaptureMouse();
            beforePositon = e.GetPosition(LayoutRoot);
            DragPanel.MouseMove += new MouseEventHandler(DragPanel_MouseMove);
}

MouseMove 이벤트 처리기에서 실질적인 Drag를 처리한다;
우선 마우스의 좌표가 변화를 구하여 beforePositon 변수에 저장한다;
beforePositon.X = e.GetPosition(LayoutRoot).X - beforePositon.X;
beforePositon.Y = e.GetPosition(LayoutRoot).Y - beforePositon.Y;

현재 컨트롤의 Margin정보를 temp 객체에 저장하고
위에서 구한 차이만큼을 가감한다; 이때 Right 와 Botton은 위에서 0으로 고정했으므로 신경 쓸 필요가 없다

변경된 Margin을 컨트롤에 적용한다;
this.Margin = temp;

 다음 드레그를 위해 현재 위치를 저장한다
 beforePositon = e.GetPosition(LayoutRoot);
void DragPanel_MouseMove(object sender, MouseEventArgs e)
{
            beforePositon.X = e.GetPosition(LayoutRoot).X - beforePositon.X;
            beforePositon.Y = e.GetPosition(LayoutRoot).Y - beforePositon.Y;
            Thickness temp = this.Margin;
            temp.Left += beforePositon.X;
            temp.Top += beforePositon.Y;
            this.Margin = temp;
            beforePositon = e.GetPosition(LayoutRoot);
}

MouseLeftButtonUp 이벤트 처리기에서는 CaptureMouse를 ReleaseMouseCapture 해준다
void DragPanel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
            DragPanel.ReleaseMouseCapture();
            DragPanel.MouseMove -= new MouseEventHandler(DragPanel_MouseMove);
}

이렇게만 해주면 마우스 드레그가 아주 잘되는 것을 확인 할 수 있다!
Posted by 맨날맑음
,


프로그래밍을 하다보면 Thread로 처리해야 하는 일들이 생기게 된다..

그런데 실버라이트에서는 객체를 컨트롤 할때 주스레드(UI thread)에서
처리 하지 않게되면 Cross Thread라는 문제를 발생시키다;
예제를 보면 쉽게 이해가 갈것이다!

구현하고자하는 프로그램!

간단히 실버라이트 page에 버튼하나와 TextBlock을 배치하여 버튼클릭시 TextBlock에
지정한 문자열을 표시하도록 했다!
-- page.xaml --

<UserControl x:Class="UIThread.Page"
    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" Background="White">
     <Button Height="85" HorizontalAlignment="Right" Margin="0,0,47,56" VerticalAlignment="Bottom" Width="142" Content="Make Thread" x:Name="btnThread"/>
     <TextBlock Height="82" Margin="22,22,32,0" VerticalAlignment="Top" Text="TextBlock" TextWrapping="Wrap" x:Name="txtTextBlock"/>
    </Grid>
</UserControl>



-- UI 화면 --



-- page.xaml.cs --

using System.Windows;
using System.Windows.Controls;
//Thread를 쓰기위한 using
using System.Threading;
namespace UIThread
{
    public partial class Page : UserControl
    {
        public Page()
        {
            InitializeComponent();
            btnThread.Click += new RoutedEventHandler(btnThread_Click);
        }

        void btnThread_Click(object sender, RoutedEventArgs e)
        {
            //Thread 생성
            Thread thread = new Thread(Doit);
            thread.Start("스레드 작업 잘될까?");
        }

        //Cross Thread 발생 Method
        void CrossThread(object state)
        {
            string txt = (string)state;
            txtTextBlock.Text = txt;
        }

        //Cross Thread 해결한 Method
        void Doit(object state)
        {
            string txt = (string)state;
            //Dispatcher 사용
            Dispatcher.BeginInvoke(
                delegate()
                {
                    txtTextBlock.Text = txt;
                }
                );           
        }
    }
}
비하인드 코드에서 보는 바와 같이 버튼을 클릭하게 되면 Thread를 하나 생성하고

일반적으로 생각하기 쉬운 방법인 CrossThread 메소드를 호출해 보았다!

-- 오류화면 --

결과는 TextBlock이라는 문자열에 전혀 변화가 없고 왼쪽 하단에 오류만 덩그러니 일어난다!
오류 정보를 보니 잘못된 크로스 스레드 액세스란다;
txtTextBlock.Text = txt; 구문때문에 ""스레드 작업 잘될까?""라는 구문이 출력해야 맞을텐데;;

이것은 바로 실버라이트 UI의 스레드 모델때문이다!
실버라이트 컨트롤의 제어는 해당하는 주스레드에서 행해져야 하지만;
우리가 강제로 쓰레드를 생성하여 컨트롤을 변경하려 했기 떄문이다;

그렇다면 해결방법은? C# 의 Delegate처럼 주스레드에 변경을 부탁하면 된다!

부탁하는 방법은 UserControl 클래스가 가지고있는  Dispatcher을 사용하면 된다!
Dispatcher의 멤버로는 Dispatcher.Invoke()와 Dispatcher.BeginInvoke()가 있다;
잘알다싶이 Invoke는 동기식 BefinInvoke는 비동기 방식이다!!!

그럼 이번엔  Dispatcher를 사용한 Doit 메소드를 호출하여 보자!!

-- 실행 화면 --

위와같이 아무런 오류없이 잘 되는것을 확인할수 있다!!
Posted by 맨날맑음
,

현재 실버라이트(Silverlight 2.0)에서는 더블클릭을 위한 이벤트가
지원되지 않아서 간단하게 DateTime객체를  을 이용하여 전체화면을 만들어 보았다;;

구현하고자 하는 프로그램!
Rectangle 객체를 더블클릭 하면 더블클릭 되었습니다! 라는 리스트 박스에 메세지 띄우기!!

1.우선 새프로젝트(실버라이트응용프로그램)를 만들고


2. 간단하게 page.xaml에 Rectangle로 만든 Button과 ListBox를 올려 놓는다!
     
     
     
      
         
           
              
              
           
         
      
      
     
 
--page.xaml--



3. page.xaml 비하인트 코드(page.xaml.cs)에 rectangle에 MouseLeftButtonDown이벤트를
 추가한다!

--page.xaml.cs--
public partial class Page : UserControl
{
        DateTime mouseLastClick=DateTime.Now.AddSeconds(-1);

        public Page()
        {
            InitializeComponent();
            MyButton.MouseLeftButtonDown += new MouseButtonEventHandler 
              (MyButton_MouseLeftButtonDown);
        }

        void MyButton_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if ((DateTime.Now - mouseLastClick).Milliseconds < 200)
            {
                MyListBox.Items.Add("더블클릭 되었습니다!");
                mouseLastClick = DateTime.Now.AddSeconds(-1);
            }
            else
            {
                mouseLastClick = DateTime.Now;                
            }
        }
}

코드에는 DateTime 마우스 처음 클릭시간을 저장하기 위해 DateTime변수를 클래스의 멤버변수로 선언했으며
MouseLeftButtonDown이벤트 메소드에
현재 마우스를 클릭한 시각 - 마지막으로 마우스를 클릭한 시각 =  0.2초를 넘지 않는다면 더블클릭으로 간주하여
더블클릭 돼었다고 메세지를 띄우게 하였다;

이때 DateTime.Now.AddSeconds(-1); -1을 대입해주는건 더블클릭이 된후 마우스클릭에대해 더블클릭으로
인지하는것을 막기 위한이다!
  (생각해봐라; 저게 없다면 3번 빠르게 누르면 더블클릭이 2회 발생한걸로 나올것이다!)

<실행 화면>
간단한 예제로 만들어본 실버라이트 마우스 더블클릭하기 !


Posted by 맨날맑음
,