Tech/Silverlight2009. 6. 11. 16:37
참고 자료 _ [강좌] ImageButton 만들기, Dependency Property의 이해

1. Blend를 통한 Image 버튼 만들기
2. 동적으로 Image 변경이 가능한 ImageButton 클래스 만들기
3. ImageButton 클래스를 사용하기


1. Blend를 통한 image 버튼 만들기

- 참고 자료에 있는 강좌를 보면 Blend를 사용해 손쉽게 Image 버튼을 생성할 수 있다. 생성한 코드를 살펴보면 다음과 같다.

Page.xaml
<UserControl.Resources>
<ControlTemplate x:Key="ImageButtonTemplate" TargetType="Button">
<Grid>
<vsm:VisualStateManager.VisualStateGroups>
<vsm:VisualStateGroup x:Name="FocusStates">
<vsm:VisualState x:Name="Unfocused"/>
<vsm:VisualState x:Name="Focused"/>
</vsm:VisualStateGroup>
<vsm:VisualStateGroup x:Name="CommonStates">
<vsm:VisualState x:Name="MouseOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="NormalButton" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="OverButton" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="Normal"/>
<vsm:VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="NormalButton" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Collapsed</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames BeginTime="00:00:00" Duration="00:00:00.0010000" Storyboard.TargetName="PressedButton" Storyboard.TargetProperty="(UIElement.Visibility)">
<DiscreteObjectKeyFrame KeyTime="00:00:00">
<DiscreteObjectKeyFrame.Value>
<Visibility>Visible</Visibility>
</DiscreteObjectKeyFrame.Value>
</DiscreteObjectKeyFrame>
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</vsm:VisualState>
<vsm:VisualState x:Name="Disabled"/>
</vsm:VisualStateGroup>
</vsm:VisualStateManager.VisualStateGroups>
<Image x:Name="NormalButton" Source="Normal.png" Stretch="Fill" />
<Image x:Name="OverButton" Source="Over.png" Stretch="Fill" Visibility="Collapsed" />
<Image x:Name="PressedButton" Source="Pressed.png" Stretch="Fill" Visibility="Collapsed" />
</Grid>
</ControlTemplate>
</UserControl.Resources>

<Grid x:Name="LayoutRoot" Background="White">
<Button Template="{StaticResource ImageButtonTemplate}" Width="300" Height="100" />
</Grid>

- 위 코드를 보면 버튼의 각각의 상태를 정의할때 StoryBoard를 사용하는 것을 알 수 있으며, 차후 버튼에 효과를 줄때 해당 StordyBoard를 사용하면 된다.


2. 동적으로 Image 변경이 가능한 ImageButton 클래스 만들기

- Button 클래스를 상속받은 클래스를 만든다. (ImageButton.cs)
- xaml 에서 Property를 설정하면 동적으로 변경될 수 있게 DependencyProperty를 추가한다.
(버튼 상태에 따른 이미지를 설정할 수 있는 Property를 각각 NormalImageSource, OverImageSource, PressedImageSource 라고 이름을 짓는다.)

NormalImageSource DenpendencyProperty를 추가한 ImageButton.cs의 소스는 다음과 같다.

ImageButton.cs
public class ImageButton : Button
{
#region NormalImageSource
public ImageSource NormalImageSource
{
get { return (ImageSource)GetValue(NormalImageSourceProperty); }
set { SetValue(NormalImageSourceProperty, value); }
}

public static readonly DependencyProperty NormalImageSourceProperty =
DependencyProperty.Register(
  "NormalImageSource",
  typeof(ImageSource),
  typeof(ImageButton),
  null);
#endregion NormalImageSource

...

}

- OverImageSource, PressedImageSource도 같은 형태로 추가하면 xaml에서 사용할 수 있는 ImageButton 클래스의 제작이 끝난다.


3. ImageButton 클래스를 사용하기

- Page.xaml에서 사용하고 있는 Button을 ImageButton으로 바꾸기 위해서는 우선 xmlns를 추가해야 한다.
xmlns:test="clr-namespace:SilverlightApplication1;assembly=SilverlightApplication1"

- 사용하고 있는 ControlTemplate을 수정한다.
<ControlTemplate x:Key="ImageButtonTemplate" TargetType="test:ImageButton">
...
<Image x:Name="NormalButton" Source="{TemplateBinding NormalImageSource}" Stretch="Fill" />
<Image x:Name="OverButton" Source="{TemplateBinding OverImageSource}" Stretch="Fill" Visibility="Collapsed" />
<Image x:Name="PressedButton" Source="{TemplateBinding PressedImageSource}" Stretch="Fill" Visibility="Collapsed" />

- Button을 ImageButton으로 변경하고 각각의 상태에 따른 이미지를 설정한다.
<test:ImageButton x:Name="TestBtn" Template="{StaticResource ImageButtonTemplate}" Width="300" Height="100" NormalImageSource="Normal.png" OverImageSource="Over.png" PressedImageSource="Pressed.png" />

- 위에 정의된 Button의 이미지를 코드 내부에서 바꾸려면 다음과 같이 하면 된다.
TestBtn.NormalImageSource = new BitmapImage(new Uri("Normal.png", UriKind.Relative));

'Tech > Silverlight' 카테고리의 다른 글

Deep Zoom Composer 에서 개별 이미지 요소 정보 얻기  (0) 2009.08.03
Silverlight 3 _ 3D  (0) 2009.06.18
Silverlight2 Unit Test  (0) 2009.05.19
Rhino Mocks in Silverlight  (2) 2009.05.15
Posted by 알 수 없는 사용자
Tech/Silverlight2009. 5. 19. 15:15

참고 자료 _ Unit Testing with Silverlight 2
원문 _ Silverlight2 Unit Test


1. Unit Test 환경 만들기
2. API Unit Test
3. UI Unit Test


1. Unit Test 환경 만들기

Silverlight에서 UnitTest 환경을 구축하기 위해서는 우선 UnitTest Framework을 준비해야 한다.
Framework는 MSDN에서 다운로드 받을 수 있다Microsoft Silverlight Unit Test Framework
(UnitTest를 위한 Template도 같이 받아두면 편리하다.)


다운로드 받은 Framework 파일은 아래 경로에 복사한다.
(Microsoft.Silverlight.Testing.dll, Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll)

%programfiles%\Microsoft SDKs\Silverlight\v2.0\Libraries\Client

다운로드 받은 Template 파일은 유저 템플릿으로 등록한다.
Template 파일의 압축을 풀어보면 Project Template과 Class Template으로 나뉘는데 각각을 아래 경로에 복사한다. (압축 파일 자체를 복사하면 된다.)

Project Template _ %userprofile%\Documents\Visual Studio 2008\Templates\ProjectTemplates
Class Template _ %userprofile%\Documents\Visual Studio 2008\Templates\ItemTemplates

<주의사항>
현재 최신 버전의 Framework에 포함된 dll 파일의 버전이 Template에 명시된 버전과 다른 문제가 있다.
정상적으로 사용하기 위해서는 Template의 내용을 수정해야 하는데, Template 파일의 압축을 풀고 각각의 Template 별로 아래의 내용을 수정하자.

2009.3.10 기준으로 
Microsoft.Silverlight.Testing.dll의 버전은 2.0.21103.1925, Microsoft.VisualStudio.QualityTools.UnitTesting.Silverlight.dll의 버전은 2.0.21024.1838 이다.

Project Template _ SilverlightTestProject.csproj 파일을 열고 각각의 Reference 버전을 수정한다.
Class Template _ MyTemplate.vstemplate 파일을 열고 각각의 Assembly 버전을 수정한다.

위 작업이 다 끝난 이후에 Visual Studio 2008을 실행시켜보면
새 프로젝트 생성시 Visual C# 카테고리를 선택하면 내 템플릿에 Silverlight Test Project가 생성되어 있고
프로젝트에 Class 추가를 실행하면 Visual C# 카테고리의 내 템플릿에 Silverlight Test Class가 등록되어 있는 것을 확인할 수 있다.



2. API Unit Test

UnitTest를 위해 UnitTestApp 라는 이름을 가진 Silverlight Application을 생성한다.
UnitTestApp에 MyTestClass 클래스를 추가하고 아래와 같은 함수를 구현한다.

public int add(int value1, int value2)
{
    return value1 + value2;
}

이제 add 함수를 테스트 하기 위해서 실제로 UnitTest를 수행할 프로젝트를 생성한다.
UnitTestApp 솔루션에 Test라는 새 프로젝트를 추가한다. (템플릿은 Silverlight Test Project를 선택한다)

생성된 Test.cs 파일을 살펴보면 Test Class 앞에는 [TestClass]가 선언 되어 있고 테스트 함수 앞에는 [TestMethod]가 선언 되어있는 것을 알 수 있다.

Test 프로젝트를 실행하면 [TestClass]로 선언된 Class 안에 포함된 [TestMethod]를 수행하여 실제 UnitTest를 수행하게 된다.

아래와 같은 Test 함수를 추가하여 add 함수를 테스트 한다.

[TestMethod]
public void AddTest()
{
MyTestClass myTestClass = new MyTestClass();
Assert.AreEqual(3, myTestClass.add(1, 2));
}

이때 MyTestClass는 Test 프로젝트에 포함되어 있지 않기 때문에 Test 프로젝트 참조에 UnitTestApp를 추가하고 Test.cs에 using UnitTestApp; 를 추가해야 정상적으로 빌드 된다.


빌드가 완료되어 Test 프로젝트를 실행하면 다음과 같은 화면을 통해 테스트가 정상적으로 수행 되었음을 알 수 있다.


테스트 오류 상황을 확인하기 위해 Assert.AreEqual(3, myTestClass.add(1, 2)); 부분을 Assert.AreEqual(5, myTestClass.add(1, 2)); 로 수정해본다. 수정 후 실행 결과는 다음과 같다.


AddTest 함수에서 오류가 발생한 것을 알 수 있으며 기대값과 실제 값을 확인할 수 있다. 이때 AddTest를 클릭하면 더 자세한 정보를 확인할 수 있다.

다음은 컬렉션의 값이 추가 되었을때 정상적으로 이벤트가 발생하는지 테스트하는 항목을 만들어본다.
MyTestClass에 다음과 같은 멤버 변수와 함수를 추가한다.

internal ObservableCollection<int> collection = new ObservableCollection<int>();

public void addCollection(int value)
{
collection.Add(value);
}

그리고 addCollection 함수를 테스트 하기 위해 Test 프로젝트의 Test 클래스에 다음과 같은 Test 함수를 추가한다.
테스트 내용은 addCollection을 한번 호출하였을 때 Collection의 값이 변동이 되었다는 이벤트를 받아 이벤트가 정상적으로 발생 되었는지, Collection에 포함된 자료의 갯수가 한개인지 확인하게 된다.

[TestMethod]
public void CollectionTest()
{
MyTestClass myTestClass = new MyTestClass();

bool changedValue = false;

myTestClass.collection.CollectionChanged += delegate(object sender, NotifyCollectionChangedEventArgs e)
{
changedValue = true;
Assert.AreEqual(NotifyCollectionChangedAction.Add, e.Action);
Assert.AreEqual(1, e.NewItems.Count);
};

myTestClass.addCollection(5);
Assert.IsTrue(changedValue);

}

이 코드를 추가하고 다시 빌드를 실행하면 internal로 선언된 collection 때문에 오류가 발생한다. 이는 Test 프로젝트와 UnitTestApp가 서로 다른 namespace이기 때문인데, 테스트를 위해서 collection을 public으로 바꾸는 방법도 있지만, UnitTestApp에 있는 AssemblyInfo.cs 파일을 수정하여 UnitTestApp에 있는 internal 을 Test 어셈블리에서도 access 가능하게 수정하도록 한다.

internal로 선언된 변수를 다른 어셈블리에 공개하려면 AssemblyInfo.cs 파일에 다음을 추가하면 된다. (AssemblyInfo.cs 파일은 Properties 폴더에 있음)

[assembly: InternalsVisibleTo("Test")]

빌드가 정상적으로 되고 Test 프로젝트를 실행하면 정상적으로 테스트를 성공하는 것을 확인할 수 있다.


3. UI Unit Test

UI를 테스트 하기 위해서는 테스트 대상이 될 어플리케이션을 임시로 생성하고 사용자 입력을 자동으로 만들어서 테스트를 수행하여야 한다.

UnitTestApp의 Page.xaml에 다음과 같은 코드를 생성하자.

<StackPanel>
<TextBox x:Name="InputText" />
<Button Content="Click" Click="Button_Click" />
<TextBlock x:Name="OutputText" />
</StackPanel>

Button을 클릭하면 InputText에 있는 내용을 OutputText로 뿌려주도록 한다.

private void Button_Click(object sender, RoutedEventArgs e)
{
OutputText.Text = InputText.Text;
}

구현한 위의 동작을 테스트 하기 위해서 Test 프로젝트에 새로운 테스트 클래스인 UITest를 생성하자. (Silverlight Test Class 템플릿을 사용)

UITest를 이용해서 어플리케이션의 UI를 테스트 하기 위해서는 [TestMethod]가 수행될 때마다 어플리케이션을 임시로 생성해야 하는데, 이것은 [TestInitialize]를 이용하여 할 수 있다. 함수 앞에 [TestInitialize]를 선언하면 그 함수는 [TestMethod]가 수행될때마다 [TestMethod]이전에 실행되어서 원하는 값들을 초기화 시킬 수 있다.
(초기화 뿐만 아니라 [TestCleanup]을 이용하여 [TestMethod] 수행 종료 이후에 테스트 후의 환경을 정리할 수도 있다.)

[TestInitialize] -> [TestMethod] -> [TestCleanup] 순서로 수행 됨

실제로 테스트를 수행하기 위해서는 [TestInitialize] 함수에서 UnitTestApp의 페이지를 생성하고, 그 페이지를 SilverlightTest 클래스안에 있는 TestPanel의 Children에 추가시켜야 한다. 이것을 위해서 실제 테스트 클래스를 SilverlightTest를 상속받는 클래스로 생성한다.

using UnitTestApp;
using Microsoft.Silverlight.Testing;

[TestClass]
public class UITest : SilverlightTest
{
private Page testPage;

[TestInitialize]
public void PreparePage()
{
testPage = new Page();
TestPanel.Children.Add(testPage);
}
}

준비가 끝났으면 실제 테스트를 수행하는 함수를 작성한다.

[TestMethod]
public void TextBoxTest()
{
testPage.InputText.Text = "TextBoxTest";
testPage.Button_Click(this, null);

Assert.AreEqual("TextBoxTest", testPage.OutputText.Text);
}

빌드를 해보면 오류가 발생한다. Page.xaml.cs 파일을 보면 Button_Click이 private으로 선언 되어 있는데 이것을 internal로 수정한다.
(internal로 수정해서 빌드가 가능한 이유는 AssemblyInfo.cs 파일에 Test 어셈블리를 internal 범위에 포함시켰기 때문이다. internal 범위에 포함시키지 않았다면 testPage의 InputText나 OutputText도 사용할 수 없다.)

빌드가 정상적으로 진행되어 실행해보면, 작성한 Page.xaml의 내용이 화면에 깜박거리면서 테스트가 진행되는 것을 볼 수 있으며 다음과 같은 결과를 확인할 수 있다. (실제로는 UI 화면이 깜박거리면서 사라진다.)




이 포스팅에 사용된 샘플 소스

저작자 표시

'Tech > Silverlight' 카테고리의 다른 글

Silverlight 3 _ 3D  (0) 2009.06.18
ImageButton 만들기  (0) 2009.06.11
Rhino Mocks in Silverlight  (2) 2009.05.15
DataGrid 사용법  (0) 2009.04.06
Posted by wafe
Tech/Silverlight2009. 5. 15. 18:41
Rhino Mocks 홈페이지

1. What is Rhino Mocks?
2. 설치
3. Silverlight Unit에서 사용하기
4. Example

1. What is Rhino Mocks?

A dynamic mock object framework for the .Net platform. It's purpose is to ease testing by allowing the developer to create mock implementations of custom objects and verify the interactions using unit testing.

Licensing: Rhino Mocks is Free Software which is released under the BSD license.




2. 설치


Rhino Mocks 3.5 - For Silverlight 

위의 파일을 받아서 압축을 풀어보면 다음과 같은 파일이 들어 있는 것을 확인할 수 있다.


테스트 프로젝트의 참조에 Rhino.Mocks 3.5 Silverlight.dll을 포함시키고 using Rhino.Mocks를 추가하면 된다.




3. Silverlight Unit에서 사용하기


Rhino Mocks를 사용하기 위해서는 다음을 지켜야 한다.

1. Mock Object로 만들 대상 Class의 함수가 상속 가능해야 한다. (virtual)

2. MockRepository에 Mock Object에 대한 선언이 끝나면 ReplayAll을 호출한다.

3. Test가 끝나면 VerifyAll을 호출해 정의한 대로 실행되었는지 확인한다.

 - VerifyAll을 호출하였을 때 정의한 대로 실행되지 않았다면 Test Fail이 발생한다.


Rhino Mocks로 클래스/인터페이스를 Mocking하기 위해서 다음과 같은 절차를 거친다.

1. MockRepository를 만든다.
ex. MockRepository mocks = new MockRepository();

2. 클래스인 경우에 PartialMock, 인터페이스인 경우에 StrickMock을 이용해 MockObject를 만든다.
ex. ContentsPlayerMain cpMain = mocks.PartialMock<ContentsPlayerMain>();

Mock Object에서 가상으로 사용할 함수를 선언한다.

return value가 있을 경우 _ Expect.Call(function)
return value가 void인 경우 _ Expect.Call(delegate{function;}) or ...; LastCall

-

Expect.Call의 Return 결과물에 새로운 Return Value나 함수 호출 횟수를 설정할 수 있다.

Expect.Call(function).Return(data); - function을 호출하면 data가 return 된다.

Expect.Call(function).Repeat.Once() - function이 한 번만 실행되는 것을 확인한다.

-

Mock Object에서 Expect.Call로 정의된 함수를 호출하게 되면 실제 Class의 해당 함수의 동작을 따르는 것이 아니라 정의한 함수의 동작을 따르게 된다.
ex. Expect.Call(cpMain.GetSynchronizeData(15)).Return(data); 
// GetSynchronizeData 함수에 15가 인자로 들어오면 data를 return 한다.

참고 자료) Rhino Mocks 3.3 Quick Reference.pdf




4. Example


- 다음과 같은 함수를 Mock Object를 통해서 테스트 해본다.

internal virtual void Synchronize(double time, bool isSeek)
{
SynchronizeData synchronizeData = GetSynchronizeData(time);
currentSlide = synchronizeData.slideIndex;
currentEvent = synchronizeData.eventIndex;
if (isSeek)
{
GotoAndStop(currentSlide, currentEvent);
}
else
{
GotoAndPlay(currentSlide, currentEvent);
}
}

위 함수에서 사용하는 클래스 멤버 함수인 GetSynchronizeData, GotoAndStop, GotoAndPlay를 Mock Object를 통해 구현하자.

1. TestCase에는 time이 15와 30이 들어온다고 가정하고, 각각의 time에  대한 Data를 미리 준비한다.
2. Mock Object를 이용해 GeySynchronizeData의 인자로 15와 30이 들어왔을 경우에 준비한 Data를 Return.
3. Mock Object를 이용해 GotoAndPlay에 1, 1이 인자로 들어오고, 한 번만 호출되는 것을 확인
4. Mock Object를 이용해 GotoAndStop에 2, 0이 인자로 들어오고, 한 번만 호출되는 것을 확인

[TestMethod]
public void TestMethod()
{
MockRepository mocks = new MockRepository();

ContentsPlayerMain cpMain = mocks.PartialMock<ContentsPlayerMain>();

SynchronizeData data1 = new SynchronizeData();
data1.slideIndex = 1;
data1.eventIndex = 1;
SynchronizeData data2 = new SynchronizeData();
data2.slideIndex = 2;
data2.eventIndex = 0;

Expect.Call(cpMain.GetSynchronizeData(15)).Return(data1);
Expect.Call(cpMain.GetSynchronizeData(30)).Return(data2);
Expect.Call(delegate { cpMain.GotoAndPlay(1, 1); }).Repeat.Once();
Expect.Call(delegate { cpMain.GotoAndStop(2, 0); }).Repeat.Once();

mocks.ReplayAll();

cpMain.Synchronize(15, false);
Assert.AreEqual(1, cpMain.CurrentSlide);
Assert.AreEqual(1, cpMain.CurrentEvent);
cpMain.Synchronize(30, true);
Assert.AreEqual(2, cpMain.CurrentSlide);
Assert.AreEqual(0, cpMain.CurrentEvent);

mocks.VerifyAll();
}


'Tech > Silverlight' 카테고리의 다른 글

ImageButton 만들기  (0) 2009.06.11
Silverlight2 Unit Test  (0) 2009.05.19
DataGrid 사용법  (0) 2009.04.06
LINQ (Language Integrated Query)  (0) 2009.04.06
Posted by 알 수 없는 사용자
Tech/Silverlight2009. 4. 6. 12:00
1. DataGrid 컨트롤은?
2. DataGrid 컨트롤에서 세부 데이타 표시하기



1. DataGrid 컨트롤은?

System.Windows.Controls 네임스페이스에 속해 있는 리스트 스타일의 컨트롤이다.

DataGrid는 UI가상화를 사용하고 있어서, 몇만 개의 데이터의 행을 지원할 있도록 보장해준다.

UI가상화란 사용자에게 보이는 모든 아이템들은 메모리 안에서 생성된다는 것을 의미한다


DataGrid 컨트롤의 실행 샘플.


2. DataGrid에서 컨트롤에서 세부 데이타 표시하기


XAML에서 DataGrid 컨트롤을 사용을 위한 NameSpace 정의.

<UserControl x:Class="DataGridSample.Page"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
    >
    <Grid x:Name="LayoutRoot" Background="White">       
        <data:DataGrid x:Name="myDataGrid" />
    </Grid>
</UserControl>


데이타 소스 설정.

myDataGrid.ItemsSource = GetEoticons();
private  List<Emotion> GetEmoticons()
{
       List<Emotion> emoticons = new List<Emotion>();
       emoticons.Add(new Emotion("철수",    "1.jpg"));
       emoticons.Add(new Emotion("영희",    "2.jpg"));
       emoticons.Add(new Emotion("바둑이", "3.jpg"));
       return emoticons;            
 }

public class Emotion
{       
        private BitmapImage icon = null;
        public Emotion(string name, string imageUrl)
        {
            Name = name;
            Icon = new BitmapImage(new Uri(imageUrl, UriKind.Relative));
        }
        public string Name
        {
            get;
            private set;
        }
        public BitmapImage Icon
        {
            get { return icon;  }
            set
            {
                icon = value;
            }
        }
}


세부 데이타 표시하기
- AutoGenerateColumns False로 설정하고, DataGrid.Columns를 사용하여 데이터를 표시할 칼럼 형식을 정의.

- DataGridTextColumn 클래스의 SortMemberPath로  정렬될 멤버 설정하여 아이템 정렬.
- DataGridTemplateColumn 클래스의 CellTemplate으로 사용자 정의(고유한 열 형식) 템프릿 생성.

<data:DataGrid x:Name="myDataGrid" AutoGenerateColumns="False" IsReadOnly="False">
      <data:DataGrid.Columns>
           <data:DataGridTextColumn Binding="{Binding Name, Mode=twoWay}" SortMemberPath="Name"/>
                <data:DataGridTemplateColumn>
                    <data:DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Image Source="{Binding Icon}" Height="100"/>
                        </DataTemplate>
                    </data:DataGridTemplateColumn.CellTemplate>    
           </data:DataGridTemplateColumn>
     </data:DataGrid.Columns>
</data:DataGrid>


DataGrid 편집 하기.
- IsReadOnly를 False로 설정
- Binding Mode를 twoWay로 설정.
- 편집과 관련된 Event. 

BiginningEdit 
- DataGridBeginningEditEventArgs파라미터 안에 Cancel속성을 True 변경하면 편집을 막을 있다.
PrepareCellForEdit 
-
DataGridTemplateColumn 내부의 콘텐트가 편집 모드가 들어갈 발생.
- BeginningEdit 이벤트에서 생성한 변화들을 다시 한번 변경할 있는 기회를 준다.

 

 


 

'Tech > Silverlight' 카테고리의 다른 글

Silverlight2 Unit Test  (0) 2009.05.19
Rhino Mocks in Silverlight  (2) 2009.05.15
LINQ (Language Integrated Query)  (0) 2009.04.06
Silverlight with WEB  (0) 2009.03.30
Posted by 알 수 없는 사용자
Tech/Silverlight2009. 4. 6. 09:02

1. What is LINQ?
2. LINQ to Objects
3. LINQ to XML


1. What is LINQ?

- LINQ를 사용하면 C#또는 비쥬얼 베이직 코드를 사용하여 서로 다른 형식의 데이터를 쿼리할 수 있다.
- 작업하는 데이터 타입과 상관없이 단일하고 일관된 쿼리 구문을 제공해준다.
- Deferred Query Execution(지연된 쿼리 실행) : 쿼리를 LINQ를 통해 전개할 때 쿼리는 실제로 실행되기 이전에 평가되지 않는다.
- Silverlight는 LINQ to JSON, LINQ to Objects, LINQ to XML을 지원한다.


2. LINQ to Objects

- LINQ to Objects는 매니지드 코드에서 객체들의 컬렉션을 대상으로 쿼리를 생성할 수 있게 해준다.

public class AddressData
{
 public string name;
 public string phoneNumber;
 public string address;
}

// 이름이 xinics인 사람의 AddressData를 얻기
List<AddressData> addressDatas;
var xinicsAddressData =
from addressData in addressDatas
where addressData.name == "xinics"
select addressData;


3. LINQ to XML

- LINQ to XML 또는 XLinq는 복잡한 XML API에 의존할 필요 없이 쉽게 XML 데이터를 생성하고 쿼리할 수 있게 해준다.

AddressData.xml
<AddressDatas>
<AddressData>
<Name>...</Name>
<PhoneNumber>...</PhoneNumber>
<Address>...</Address>
</AddressData>
</AddressDatas>

// 이름이 xinics인 사람의 AddressData를 얻기
XElement element = XElement.Load("AddressData.xml");
var xinicsAddressData =
from addressData in element.Descendants("AddressData")
where (string)addressData.Element("Name") == "xinics"
select new AddressData
{
Name = addressData.Element("Name").Value,
PhoneNumber = addressData.Element("PhoneNumber").Value,
Address = addressData.Element("Address").Value
};

'Tech > Silverlight' 카테고리의 다른 글

Rhino Mocks in Silverlight  (2) 2009.05.15
DataGrid 사용법  (0) 2009.04.06
Silverlight with WEB  (0) 2009.03.30
Loading Dynamic XAPs and Assemblies  (0) 2009.03.19
Posted by 알 수 없는 사용자
Tech/Silverlight2009. 3. 30. 21:07
Silverlight 어플리케이션이 WEB과 어떤 연관을 가지고 있는지 알아보자.

1. Silverlight Application을 HTML 페이지에 삽입
2. Background, IsWindowless
3. OnLoad, OnError
4. HTML DOM과 상호 작용하기
4.1. Javascript로 Silverlight 코드 사용하기
4.2. Silverlight로 Javascript 코드 사용하기


1. Silverlight Application을 HTML 페이지에 삽입

- Silverlight는 브라우저의 플러그인 형태로 만들어졌다. 하지만 배포 방식에 따라 브라우저 별로 각각 다르게 사용된다.
 Microsoft Internet Explorer  Active-X 
 Safari   Webkit 
 Other  Netscape Plug-in 


a. ASP.NET을 이용한 방법
- Visual Studio 2008을 이용해 Silverlight Application을 생성하면 자동으로 생성되는 aspx 페이지에 Silverlight Application이 삽입되어 있는 것을 확인할 수 있다.
<%@ Register Assembly="System.Web.Silverlight" Namespace="System.Web.UI.SilverlightControls"
    TagPrefix="asp" %>

<asp:Silverlight ID="Xaml1" runat="server" Source="~/ClientBin/SilverlightHTML.xap" MinimumVersion="2.0.31005.0" Width="100%" Height="100%" />


b. <object> 태그를 사용하여 생성
<object data="data:application/x-silverlight-2,"  type="application/x-silverlight-2" width="100%" height="100%">
<param name="source" value="ClientBin/SilverlightHTML.xap"/>
<param name="onerror" value="onSilverlightError" />
<param name="background" value="white" />
<param name="minRuntimeVersion" value="2.0.31005.0" />
<param name="autoUpgrade" value="true" />
</object>


c. Silverlight.js를 사용하여 생성
- Silverlight SDK에서 제공되는 Silverlight.js 파일을 이용하면 편리하게 Silverlight Application을 생성할 수 있다.
<div id="silverlightControlHost" />
<script language="javascript">
Silverlight.createObjectEx({
source: "ClientBin/SilverlightHTML.xap",
parentElement: document.getElementById("silverlightControlHost"),
id: "mySilverilghtControl",
properties: {
width: "100%",
height: "100%",
version: "2.0"
},
events: {}
});
</script>



2. Background, IsWindowless

- Silverlight에서 Background의 속성을 'transparent'로 설정하고 IsWindowless의 속성을 'true'로 설정하면 Silverlight Application의 배경이 설정되지 않는 빈 영역에 HTML의 내용이 그대로 보여진다. (asp.net 페이지에서 사용하는 속성 이름은 PluginBackground, Windowless이다.)

<Canvas Width="200" Height="200">
<Canvas Width="100" Height="100" Canvas.Left="50" Canvas.Top="50" Background="BlueViolet"/>
</Canvas>

<asp:Silverlight PluginBackground="Transparent" Windowless="true" ... />

- Transparent를 통해 실제 HTML 페이지가 보여지는 영역도 Silverlight Application의 영역으로 설정되어 마우스 오른쪽 클릭을 하면 Silverlight 메뉴가 나타난다.


3. OnLoad, OnError

- Silverlight 플러그인은 OnLoad와 OnError 이벤트를 가지고 있다.

OnLoad _ Silverlight Application이 로드되자마자 발생하는 이벤트
OnError _ Silverlight Application에서 예외가 처리되지 않은 경우에 발생

OnLoad 이벤트는 UserControl의 생성자가 실행된 이후에 발생한다.

테스트 결과 OnLoad 이벤트에서 Source가 undefined로 전달된다. 따라서 Silverlight Application에 직접 접근하기 위해서는 OnLoad 이벤트에서 전달되는 sender를 사용한다. sender.getHost().content를 통해 접근 가능


4. HTML DOM과 상호 작용 하기

- System.Windows.Browser 네임스페이스를 통해 HTML DOM과 상호작용이 가능하다.

4.1과 4.2의 내용은 HTML BROWSER INTEGRATION을 참조

'Tech > Silverlight' 카테고리의 다른 글

DataGrid 사용법  (0) 2009.04.06
LINQ (Language Integrated Query)  (0) 2009.04.06
Loading Dynamic XAPs and Assemblies  (0) 2009.03.19
USING STARTUP PARAMETERS WITH SILVERLIGHT  (0) 2009.03.18
Posted by 알 수 없는 사용자
Tech/Silverlight2009. 3. 19. 00:52
참고 자료 _ Loading Dynamic XAPs and Assemblies

1. What is Assembly?
2. XAP를 다운로드 하기
3. XAP에서 AppManifest.xaml 추출해 내기
4. AppManifest에 정의된 Assembly를 로드하기
5. 로드된 어셈블리에 있는 UserControl 생성하기


1. What is Assembly?


In the Microsoft .NET framework, an assembly is a partially compiled code library for use in deployment, versioning and security

Assembly는 다음과 같은 특징을 가진다.

1. 어셈블리는 코드들의 논리적인 묶음이다.
2. 어셈블리는 물리적으로 DLL또는 EXE로 존재한다.
3. 한 개의 어셈블리는 한 개이상의 파일을 포함할 수 있다.


2. XAP를 다운로드 하기

Silverlight 어플리케이션 내에서 미리 컴파일된 Silverlight Application(.xap)을 불러들이기 위해서는 WebClient를 사용한다. 불러들인 결과물의 타입은 Stream이다.

WebClient c = new WebClient();
c.OpenReadCompleted += new OpenReadCompletedEventHandler(c_OpenReadCompleted);
c.OpenReadAsync(new Uri("DynamicXAPDataGrid.xap", UriKind.Relative));

void c_OpenReadCompleted(object sender, OpenReadCompletedEventArgs e)
{
// e.Result를 통해 xap의 Stream을 사용할 수 있다.
}

참고 사항
Silverlight 기반 응용 프로그램을 빌드하면 XAP가 만들어 진다. XAP 파일은 응용 프로그램을 시작하는데 필요한 모든 파일을 포함하는 압축된 ZIP 파일이다.

XAP 파일에는 다음과 같은 파일이 들어 있다.

1. 패키지된 어셈블리 및 응용 프로그램 진입점을 식별하는 AppManifest.xaml 파일 한 개 
2. 응용 프로그램 클래스가 들어 있는 응용 프로그램 어셈블리 한 개 
3. 0개 이상의 라이브러리 어셈블리 
4. 이미지나 비디오 파일 같은 느슨한 리소스 파일 0개 이상 


3. XAP에서 AppManifest.xaml 추출하기 

XAP 파일의 Stream에서 AppManifest.xaml 파일의 내용을 추출하기 위해서는 Application.GetResourceStream을 사용한다. GetResourceStream을 사용하면 지정한 zip 패키지에서 특정한 리소스 파일을 얻을 수 있다. (얻을 수 있는 값은 StreamResourceInfo 타입이다.)

Application.GetResourceStream(new StreamResourceInfo(e.Result, null), new Uri("AppManifest.xaml", UriKind.Relative))

AppManifest.xaml 파일의 StreamResourceInfo를 얻었다면 그 파일의 Stream을 XML 파싱을 위해 String 형태로 변환한다.

string appManifest = new StreamReader(appManifestStreamInfo.Stream).ReadToEnd();

그리고 얻어낸 string을 System.xml.Linq를 이용해 파싱하여 AssemblyPart 부분을 List로 만들어 둔다.

XElement deploy = XDocument.Parse(appManifest).Root;
List<XElement> parts = (from assemblyParts in deploy.Elements().Elements()
select assemblyParts).ToList();

제 사용한 DynamicXAPDataGrid.xap 파일에 포함된 AppManifest.xaml 파일의 내용은 다음과 같다. 이를 살펴보면 이 xap에 포함된 어셈블리가 무엇인지 확인할 수 있다.

<Deployment xmlns="http://schemas.microsoft.com/client/2007/deployment" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" EntryPointAssembly="DynamicXAPDataGrid" EntryPointType="DynamicXAPDataGrid.App" RuntimeVersion="2.0.31005.0">
  <Deployment.Parts>
    <AssemblyPart x:Name="DynamicXAPDataGrid" Source="DynamicXAPDataGrid.dll" />
    <AssemblyPart x:Name="System.Windows.Controls.Data" Source="System.Windows.Controls.Data.dll" />
    <AssemblyPart x:Name="System.Windows.Controls" Source="System.Windows.Controls.dll" />
    <AssemblyPart Source="ko/System.Windows.Controls.resources.dll" />
    <AssemblyPart Source="ko/System.Windows.Controls.Data.resources.dll" />
  </Deployment.Parts>
</Deployment>


4. AppManifest에 정의된 Assembly를 로드하기

불러들인 Silverlight 어플리케이션을 사용하기 위해서는, XAML 파일에 정의된 Assembly 파일들을 모두 로드해줘야 한다. AppManifest.xaml에서 얻어 둔 Assembly 들의 경로를 참조하여 로드한다. XAP에 포함된 어셈블리를 로드하기 위해서는 AssemblyPart 클래스를 사용한다.

Assembly asm = null;
foreach (XElement xe in parts)
{
string source = xe.Attribute("Source").Value;
AssemblyPart asmPart = new AssemblyPart();
StreamResourceInfo streamInfo = Application.GetResourceStream(
new StreamResourceInfo(e.Result, "application/binary"), new Uri(source, UriKind.Relative));
if (source == "DynamicXAPDataGrid.dll")
{
asm = asmPart.Load(streamInfo.Stream);
}
else
{
asmPart.Load(streamInfo.Stream);
}
}

AssemblyPart들 중에서 실제 Silverlight 어플리케이션인 DynamicXAPDataGrid.dll 파일은 로드를 실행하고 그 Assembly 객체를 변수에 담아둔다.


5. 로드된 어셈블리에 있는 UserControl 생성하기

실제 Silverlight 어플리케이션 Assembly 객체에서 CreateInstance를 호출해 어플리케이션 내에 포함된 UserControl 객체를 생성할 수 있다.

UserControl myControl = asm.CreateInstance("DynamicXAPDataGrid.Page") as UserControl;


'Tech > Silverlight' 카테고리의 다른 글

LINQ (Language Integrated Query)  (0) 2009.04.06
Silverlight with WEB  (0) 2009.03.30
USING STARTUP PARAMETERS WITH SILVERLIGHT  (0) 2009.03.18
HTML BROWSER INTEGRATION  (0) 2009.03.16
Posted by 알 수 없는 사용자
Tech/Silverlight2009. 3. 18. 19:32
HTML에서 SILVERLIGHT로 초기화 매개변수 전달하는 방식
1. Object initParams으로  전달방식
2. HTML QueryString으로 전달하는 방식

1. ObjectinitParams으로  전달방식
   여러개를 initParams으로 전달
<param name="initParams" value="firstname=a,lastname=i" />


  전달받은 초기화 매개변수를 전달 받는다.
private void Application_Startup(object sender, StartupEventArgs e)
{
if (e.InitParams != null)
{
          foreach (var item in e.InitParams)
          {
                   this.Resources.Add(item.Key, item.Value);
     //application-scope내에서 리소스로 저장한다.
            }
          }
            string fname = string.Empty;
            if (e.InitParams.Keys.Contains("firstname"))
            {
                fname = e.InitParams["firstname"].ToString();
            }
            this.RootVisual = new Page(fname);
}


2. HTML QueryString으로 전달하는 방식
 직접 링크를 전달해 줄 수 있다는 장점이 있음
foreach (var itme in HtmlPage.Document.QueryString)
{
TextBlock tb = new TextBlock();
 tb.Text = string.Format("{0}:{1}", itme.Key, itme.Value);
 InitParams.Children.Add(tb);
}

'Tech > Silverlight' 카테고리의 다른 글

Silverlight with WEB  (0) 2009.03.30
Loading Dynamic XAPs and Assemblies  (0) 2009.03.19
HTML BROWSER INTEGRATION  (0) 2009.03.16
Isolated Storage in Silverlight 2  (0) 2009.03.16
Posted by 알 수 없는 사용자
Tech/Silverlight2009. 3. 16. 19:52
HTML BROWSER INTEGRATION

1. Javascript에서 Silverlight 모듈내에 정의된 메소드 사용하기.
2. Silverlight에서 Javascript에서 정의된 메소드 호출하기.
3. Silverlight Event 연동.


1. Javascript에서 Silverlight 모듈내에 정의된 메소드 사용하기.  
  Silverlight에서 작성된 메소드를 JavaScript에서 액서스 가능하도록 설정.
//JavaScript에서 인식 가능한 Object로 등록.
HtmlPage.RegisterScriptableObject("slInternal", this);
//액서스 가능하도록 설정.
[ScriptableMember]
public string SayHelloToMe(string firstName)
{
  Block1.Text = firstName;
  return "성공";
}

 JavaScript에서 Silverlight 메소드 호출.
var slObj = document.getElementById("Xaml1");       

var ret = slObj.content.slInternal.SayHelloToMe("자이닉스");



2. Silverlight에서 Javascript에 정의된 메소드 호출하기
 Javascirpt 함수 작성.

<script type="text/javascript">

function sayGoodbye(name)

{

   alert( "name : " + name);
  
return "성공";

}

</script>


 Silverlight에서 Javascript 존재하는 함수 호출

string ret = (string) HtmlPage.Window.Invoke("sayGoodbye", "자이닉스");

또는
ScriptObject jsObj = (ScriptObject)HtmlPage.Window.GetProperty("sayGoodbye");
string ret = (string)jsObj.InvokeSelf(TextBox1.Text, 1000);


3. Silverlight Event 연동.
 이벤트 정의
[ScriptableType]

public class CompletedEventArgs : EventArgs

{

public CompletedEventArgs(string status, string result)

{

Status = status;

Result = result;

}

 

[ScriptableMember]

public string Status { get; set; }

public string Result { get; set; }

}


 델리게이트를 ScriptableMember로 선언.

[ScriptableMember]

public event EventHandler<CompletedEventArgs> Completed;

private void OnCompleted(string status, string result)

{

if (Completed != null)

{

CompletedEventArgs args = new CompletedEventArgs ( status, result );

Completed(this, args);

}


}

 버튼을 클릭했을 때, 이벤트 발생.
 private void Button2_Click(object sender, RoutedEventArgs e)

 {

            OnCompleted("OK", "자이닉스");           

 }


 Javascript에서 Silverlight에서 발생되는 이벤트 연결.
function bind()

{

var slObj = document.getElementById("Xaml1");

alert(slObj.content.slInternal);

slObj.content.slInternal.Completed = function(sender, a) 

{

// sender는 Silverlight 객체이다. (slObj.content.slInternal)

alert(a.Result);

}

}




참고
HTML 페이지에서 Silverlight에 있는 이벤트를 연결할 때, HTML 페이지의 OnLoad 이벤트에서 처리하게 되면 Silverlight 어플리케이션이 생성되어 있지 않을 수도 있기 때문에 스크립트 오류를 발생시킬 수 있다. 이것을 정상적으로 처리하기 위해서는 Silverlight 어플리케이션의 로드가 끝난 시점에 HTML 페이지에 Silverlight 어플리케이션이 로드 되었다는 것을 알려주고, 그 때 HTML 페이지에서 Silverlight의 이벤트 연결 작업을 하면 된다.
Silverlight 로드 완료 -> HTML 페이지에 전달 -> HTML 페이지에서 Silverlight 어플리케이션 이벤트 연결




'Tech > Silverlight' 카테고리의 다른 글

Silverlight with WEB  (0) 2009.03.30
Loading Dynamic XAPs and Assemblies  (0) 2009.03.19
USING STARTUP PARAMETERS WITH SILVERLIGHT  (0) 2009.03.18
Isolated Storage in Silverlight 2  (0) 2009.03.16
Posted by 알 수 없는 사용자
Tech/Silverlight2009. 3. 16. 17:48
참고 자료 

1. What is Isolated Storage?
2. Isolated Storage를 사용하여 Data 저장 / 불러오기
3. Isolated Storage를 사용하여 File 저장 / 불러오기
4. Isolated Storage 저장 공간 늘리기
5. Data와 File은 어디에 있을까?
6. IsolatedSettings.ApplicationSetting vs IsolatedSettings.SiteSettings


1. What is Isolated Storage?

응용 프로그램이 부분 신뢰 응용 프로그램에 대해 안전한 클라이언트측 가상 파일 시스템을 만들고 유지 관리하도록 할 수 있습니다. Silverlight에서 모든 I/O 작업은 격리된 저장소로 제한되며 운영 체제의 파일 시스템을 사용하지 않습니다. (Cache와 비슷한 개념이다. 단 Isolated Storage는 File Writing이 가능하다.)


2. Isolated Storage를 사용하여 Data 저장 / 불러오기


private IsolatedStorageSettings appSetting = IsolatedStorageSettings.ApplicationSettings;

private void Save()
{
if (!appSetting.Contains("UserName"))
{
appSetting.Add("UserName", string.Empty);
}

appSetting["UserName"] = "myiris12";
}

private void load()
{
if (appSetting.Contains("UserName"))
{
string userName = appSetting["UserName"].ToString();
}
}


3. Isolated Storage를 사용하여 File 저장 / 불러오기


private void write(object sender, RoutedEventArgs e)
{
IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();

StreamWriter sw = new StreamWriter(store.OpenFile("foo.txt", FileMode.Create));
sw.WriteLine(UserName.Text);
sw.Close();
}

private void read(object sender, RoutedEventArgs e)
{
IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();

StreamReader sr = new StreamReader(store.OpenFile("foo.txt", FileMode.Open));
string userName = sr.ReadToEnd();
sr.Close();
}


4. Isolated Storage 저장 공간 늘리기

- 새로 할당될 용량은 기존 확보한 용량보다 커야 함 (작거나 같으면 Exception이 발생한다)
- IsolatedStorageFile을 이용하여 현재 사용 가능한 용량과 전체 용량을 알 수 있다.

IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
현재 사용 가능한 용량_ store.AvailableFreeSpace
전체 용량 _ store.Quota

IsolatedStorageFile store = IsolatedStorageFile.GetUserStoreForApplication();
store.IncreaseQuotaTo(10 * 1024 * 1024); // byte 단위로 용량을 산정한다.

- IncreaseQuotaTo 함수를 실행하면 다음과 같은 화면을 통해 용량을 늘릴 수 있다.


- 사용한 저장 공간과 전체 저장 공간은 Silverlight Application에서 오른쪽 클릭을 하여 나타나는 메뉴에서 확인할 수 있다.



5. Data와 File은 어디에 있을까?

6. IsolatedSettings.ApplicationSetting vs IsolatedSettings.SiteSettings

a. ApplicationSettings _ 응용 프로그램별, 컴퓨터별 및 사용자 설정별로 저장되며, 그 범위는 응용 프로그램 .xap 파일의 전체 경로를 통해 확인됩니다. 
b. SiteSettings _ 도메인별, 컴퓨터별 및 사용자 설정별로 저장되며, 그 범위는 응용 프로그램 .xap 파일을 호스팅하는 하위 도메인을 통해 확인됩니다.

예를 들어 http://domain/site1/application.xap의 응용 프로그램은 http://domain/site2/application.xap의 응용 프로그램과 다른 ApplicationSettings를 갖지만 두 응용 프로그램은 모두 동일한 하위 도메인에서 호스팅되므로 동일한SiteSettings를 공유합니다.

'Tech > Silverlight' 카테고리의 다른 글

Silverlight with WEB  (0) 2009.03.30
Loading Dynamic XAPs and Assemblies  (0) 2009.03.19
USING STARTUP PARAMETERS WITH SILVERLIGHT  (0) 2009.03.18
HTML BROWSER INTEGRATION  (0) 2009.03.16
Posted by 알 수 없는 사용자