http://www.sharpgis.net/post/2009/07/09/Silverlight-3-Released.aspx 여기에 잘 포스팅 되어 있고, 저도 해봤어요.

1. MouseWheel이 드디어 지원되네요 :D
중요한 사실을 빼먹었네요. 이 MouseWheel 이벤트는 FullScreen에서도 지원된다는 사실! 우오오오옷!

2. 구동 환경이 Windows 7일 경우 멀티터치를 지원!! 우오오오옷!!!!!
근데 난 터치디바이스가 없을 뿐이고 ㅠ.ㅜ

3. 8bit 투명 PNG 지원. 아쉽게도 1,2,4bit는 지원 안한다는군요. ㅠ.ㅜ

4. Out-of-browser 기능을 프로젝트 속성에서 GUI로 조절 가능.

5. 기본 Behavior가 제공됨.
진짜 뭘 하든 꼭 필요한 것들만 모아둔 것 같아요!

사소한거지만 메인 페이지의 XAML에서 기본 배경색상이 투명으로 바뀌었고 블렌드를 위한 xmlns가 기본으로 정의 되었네요.

우와왕ㅋ굳ㅋ!!! 으아아아아 빨리 쓰고 싶다 >_<

저작자 표시 동일 조건 변경 허락
신고
Posted by gongdo
Because Behaviors are not FrameworkElements, you can't use DataBinding with Behaviors. I posted this about it before.

<Button Content="Description">
    <i:Interaction.Triggers>
        <i:EventTrigger EventName="Click">
            <local:ShowMessageBoxAction Message="{Binding Description}" />
        </i:EventTrigger>
    </i:Interaction.Triggers>
</
Button>
[You can't use DataBinding with Behaviors like above]

Well, I'm still thinking about that it's the best way to use DataBinding with Behaviors. Why I can't do like that! However, if you really want to mix up DataBinding and Behaviors just like me, there are some work-arounds.

First, you can attach a 'Binder' class to FrameworkElement as an AttachedProperty. Morten Nielsen writed such a cool class, 'SurrogateBinder' which is general data binding helper. It could be attached to any FrameworkElement, and it passes through the value which from data source to actual target. Here's sample code:

<TextBox RenderTransformOrigin="0.5,0.5"
        Text="Hello Universe!"
        binders:SurrogateBind.Value="{Binding Path=MoreValues.Heading}" 
        binders:SurrogateBind.Target="RenderTransform.Children.Item[1].Angle" >
    <TextBox.RenderTransform>
        <TransformGroup>
            <ScaleTransform />
            <RotateTransform />
        </TransformGroup>
    </TextBox.RenderTransform>
</TextBox>

It works well with any property of FrameworkElement but not for AttachedProperty like Behaviors. So you must modify little bit to targeting AttachedProperty. Also SurrogateBinder can't be set on Blend, so most of designers might not want to use it. Blend-support is important for XAML design. So I don't prefer in-line AttachedProperty as a solution, even though it is cool & smart.

SecondPete Blois who is a program manager of Expression Blend introduced this article to show how Binding property could be used with Blend for binding to non-FrameworkElement, like Behaviors. As you know, we can't use DataBinding to properties on Behaviors, 'cause Behavior is not a FrameworkElement. But Blend seems to allow DataBinding to a property which is type of Binding. Hey! it's so tricky isn't it? :(

<i:Interaction.Behaviors>
    <id:DataStateBehavior Binding='{Binding IsOnline}' Value='True'/>
</i:Interaction.Behaviors>
[You can use DataBinding only on a property which is type of Binding. Could you guess that?]

It looks much cooler than other, but it's not a general solution. Imagine that you want to bind to 3rd party's Behavior, you nerver can do, of course it might has no Binding property! However, sample is just sample and actually it's not only for DataBinding with Behavior but also for Trigger which is raised by condition of data.

Thrid. Now, here's my approach.

<i:Interaction.Triggers>
    <i:EventTrigger EventName="Click">
        <hi:ShowMessageBoxAction x:Name="ShowMessageAction"/>
    </i:EventTrigger>
</i:Interaction.Triggers>
<i:Interaction.Behaviors>
    <hi:BindingProxyBehavior
        TargetName="ShowMessageAction"
        TargetPropertyName="Message"
        Binding="{Binding Path=Description}" />
</i:Interaction.Behaviors>


Sigh, looks messy huh? But it based on standard Behavior, so it works well with Blend and you don't need to worry about writing these XAML code. Blend will generate XAML code as well as you write.
'BindingProxyBehavior' implements Behavior class, and it exposes  some properties which are needed to determine DataBinding & binding target. It focuses only one binding per an instance, but you can attach multiple instance of it, 'cause it's a standard Behavior.

Here's sample project. Enjoy it :)


Actually I'dont like any of them, but first code-block which is impossible currently. So I really want to say, why not with DataBinding? Please?
저작자 표시 동일 조건 변경 허락
신고
Posted by gongdo

XAP 사이즈, 압축하지 않겠는가?에서 얘기한 것 처럼 실버라이트 배포에 가장 중요한 점 중 하나는 바로 용량을 줄이는거죠. 그래서 배경화면이나 복잡한 디자인 등에 사용하는 이미지 파일은 프로젝트에 포함하지 않고 웹 서버쪽에 두는 것이 정석이에요. 그런데 이렇게 하면 개발자들이야 어차피 디자인을 보면서 작업하는 일이 많지 않아서 별로 문제가 안되지만, 디자이너들에겐 치명적인 문제가 되죠. 생각해보세요 배경화면을 보면서 디자인을 해야 하는데 이미지가 프로젝트에 없어서 보이지 않는다니!

요컨대, 다음과 같이 배경 이미지 한장을 보여주는 아주 간단한 샘플을 놓고 보죠.

image image

최초로 Images 폴더에 ducks.jpg를 추가하면 기본적으로 Build Action이 Resource가 되어 프로젝트를 빌드할 때 어셈블리에 리소스로 포함되고 이 이미지의 용량은 고스란히 XAP파일의 용량이 증가하는 결과로 이어지죠. 그렇다고 이미지를 삭제하고 웹서버에만 놓기엔 디자이너가 볼 수가 없어서 애매하죠.

이럴 때는 간단하게 해당 이미지 파일을 프로젝트에 그대로 놓은 상태에서 Build Action만 None으로 설정하세요.

image

이렇게 하면 비주얼 스튜디오의 디자인 뷰에는 나오지 않지만 블렌드로 열어보면…

image

잘 보이죠? 그러면서도 배포 사이즈는 이미지의 크기가 빠지게 되죠.

별거 없지만 첨부된 프로젝트를 보면서 참고하세요.


저작자 표시 동일 조건 변경 허락
신고
Posted by gongdo

IsolatedStorage를 사용하면 Blend에서 디자인이 안보인다?에서 DesignerProperties 클래스를 활용하여 Blend에서 실행중인지 여부를 구분할 수 있다고 했는데요, DesignerProperties를 보다 정확하게 활용할 수 있는 간단한 방법을 소개합니다.

기본적으로 DesignerProperties는 다음과 같이 사용하면 되죠.

if (DesignersProperties.GetIsInDesignMode(AnyUIElementInVisualTree) == true)
    // 디자인 모드
else
    // Web 모드

간단하죠? 그런데 한 가지 문제는 반드시 인자로 VisualTree에 올라가 있는 UIElement를 필요로 한다는 점이에요. 보통 UserControl이나 Control 안에 코드를 작성할 때에는 단순히 GetIsDesignerMode(this)를 해도 무방하지만 Model과 같이 따로 UIElement를 확정할 수 없는 코드에서는 난감하죠. 이럴 때에는 다음과 같이 해결할 수 있어요.

if (DesignersProperties.GetIsInDesignMode(Application.Current.RootVisual) == true)
    // 디자인 모드
else
    // Web 모드

Application이 지원하는 RootVisual은 전역에서 일관적으로 접근할 수 있는데다가 비주얼 트리VisualTree의 최상위 오브젝트를 의미하니까 완벽해 보여요. 그렇지만 여기에도 문제는 있는데요, 바로 Application이 아직 RootVisual을 결정하지 못한 상태일 때에 이 검사는 실패한다는 점이죠. 일반적인 실버라이트 애플리케이션의 App.xaml.cs를 보죠.

public App()
{
    this.Startup += this.Application_Startup;
    this.Exit += this.Application_Exit;
    this.UnhandledException += this.Application_UnhandledException;

    InitializeComponent();
}

private void Application_Startup(object sender, StartupEventArgs e)
{
    this.RootVisual = new Page();
}

7행의 InitializeComponent();가 실행되기 직전에는 Application.Current.RootVisual이 실버라이트 애플리케이션을 다운로드 받는 동안 보이는 로딩 화면Splash에 대한 비주얼 트리를 담고 있죠.

image

그 후 애플리케이션이 초기화 되고 로딩 화면이 사라진 후 Application_Startup 이벤트 핸들러가 호출되는데요, 12행의 RootVisual을 new Page로 설정하기 직전까지는 Application.Current.RootVisual이 null 값을 가지고 있어요.

즉, 애플리케이션이 초기화 된 직후부터 RootVisual을 설정하기 전까지 Application.Current.RootVisual이 null이므로 이 사이에는 DesignerProperties.GetIsDesignMode(Application.Current.RootVisual)이란 코드는 안전하지 않게 되는거죠. 한 가지 다행인 점은 앞서 본 것 처럼 App 클래스의 생성자에서 RootVisual이 null이 아니기 때문에 이를 이용하여 다음과 같이 안전한 코드를 작성할 수 있어요.

// 초기값은 블렌드에서 실행중이라고 가정합니다.
private bool _isBlend = true;
/// 
/// 블렌드에서 실행중인지 여부를 반환합니다.
/// 
public bool IsBlend
{
    get { return _isBlend; }
    private set { _isBlend = value; }
}

public App()
{
    // 블렌드에서 실행중인지 여부를 검사합니다.
    IsBlend = DesignerProperties.GetIsInDesignMode(RootVisual);

    this.Startup += this.Application_Startup;
    this.Exit += this.Application_Exit;
    this.UnhandledException += this.Application_UnhandledException;

    InitializeComponent();
}

여기서 중요한 점은 최초에는 블렌드에서 실행중이라고 가정한다는 거에요. 그 이유는 내부적으로 블렌드에서 실행될 때에 분명히 Application의 생성자가 호출되지만 우리가 그것을 확인할 수 없기 떄문에 실행 코드의 ‘모호성’을 줄이기 위해서에요. 반면 웹 페이지로 동작하고 있다면 이 코드는 100% 동작한다고 확신할 수 있으니 초기 값을 안전하기 가져가는 것이 좋겠죠.

그리고 코드를 애플리케이션 전역에서 공유할 수 있도록 App 클래스의 static 멤버로 정의했기 때문에 애플리케이션의 어떤 코드에서도 안전하게 가져갈 수 있겠죠.

만약 라이브러리에서도 블렌드에서 실행중인지 여부를 검사해야 한다면 여기에서 한 단계 더 나아가 위의 코드를 래핑하는 전역 클래스Static Class를 하나 만들 수도 있고요. 이 부분은 각자 프로젝트에 맞춰서 해보세요.

저작자 표시 동일 조건 변경 허락
신고
Posted by gongdo

개발자들이 블렌드에서 작업을 하기 꺼려하는 이유 중 하나는 바로 XAML을 직접 편집할 때 인텔리센스를 지원하지 않는 다는 점이죠!

잘 알려지진 않았지만 블렌드는 외부 애드인을 사용할 수 있는 준비가 되어 있는데요, 이미 블렌드 2의 CTP 시절에 애드인을 사용하여 인텔리센스를 지원하는 방법이 코드플렉스에 소개되었었죠.

참고 : Intellisense For Expression Blend

당연하겠지만 버전 문제로 위의 링크에 있는 코드는 제대로 동작하지 않아요. 다행히 소스를 제공하기에 새 블렌드 버전에 맞춰서 어셈블리 참조만 바꿔서 동작하도록 수정했고 설치도 한방에 되도록 간단한 커맨드 라인 툴도 만들었어요.

 

파일을 다운 받아 압축을 해제한 후 install.cmd를 반드시! 관리자 권한으로 실행하면 다음과 같이 설치되었다는 메시지가 표시되고 끝. 간단하죠?

그런데 블렌드의 애드인은 설정 등의 값으로 설정하는 것이 아니라 매 실행마다 파라미터를 통해 전달해줘야 해요. 그래서 Blend.exe를 직접 실행해서는 안되고 바로 가기 링크를 바꿀 필요가 있죠. 위의 설치 과정에서 자동으로 바로 가기의 링크도 수정해줘요. 단, 해당 바로 가기는 Windows Vista 이상에서만 동작할거에요. XP에서 사용중이라면 다음과 같은 커맨드라인 파라미터를 사용하여 애드인을 실행해야 해요.

start Blend.exe -addin:Addins\Expression.Blend.IntelliSense.dll

위의 명령어는 블렌드가 설치된 C:\Program Files\Microsoft Expression\Blend 2\Blend.bat 라는 이름으로 자동으로 복사가 되니 참고하세요.

 

여튼 이렇게 프로그램 바로 가기로 실행하면…

XAML 뷰에서 인텔리센스가 지원되는 것을 볼 수 있어요. 물론 비주얼 스튜디오에서 지원하는 것에 비교하면 정말 허접하지만 그나마 없는 것보다는 낫네요. 또 한가지 아쉬운 점은 Split 모드에서는 인텔리센스가 지원되지 않는 다는 점인데 혹시 관심 있는 분이라면 코드플렉스에서 소스를 다운받아 수정해 볼 수도 있겠죠.

저작자 표시 동일 조건 변경 허락
신고
Posted by gongdo

Source 먼저 x:Name 어트리뷰트가 "Output"으로 설정된 TextBlock만을 가진 MyUserControl이라는 유저 컨트롤의 코드 비하인드에 다음의 코드를 입력하고 다른 유저 컨트롤(Page)에 MyUserControl을 추가 했어요.

using System;
using System.Windows.Controls;
using System.IO.IsolatedStorage;

namespace IsolatedStorageCrashInBlend
{
    public partial class MyUserControl : UserControl
    {
        public MyUserControl()
        {
            InitializeComponent();

            // 디자인 모드가 아닐 경우에만 처리
            // 설정을 읽어 Output에 출력
            if (IsolatedStorageSettings.ApplicationSettings.Contains("LastGuid"))
            {
                Output.Text = IsolatedStorageSettings.ApplicationSettings["LastGuid"].ToString();
            }
            else
            {   // 설정이 없으면 새 값을 저장
                IsolatedStorageSettings.ApplicationSettings["LastGuid"] = Guid.NewGuid().ToString();
            }
        }
    }
}

Incorrect IsolatedStorage와 관련된 코드를 포함하는 컨트롤 자체는 블렌드에서 디자인이 잘 보여요. 이유는 이 전에 포스팅 했고요.

Correct 그러나 IsolatedStorage와 관련된 코드를 포함하는 컨트롤을 다른 컨트롤의 XAML에서 추가했을 때 블렌드에서 디자인이 안보이면서 복장터지는 에러 메시지만 내뿜죠.

Solution 이 문제는 이 전 포스팅에서 얘기했듯이 DesignerProperties를 사용하여 피해갈 수 있어요.

using System;
using System.Windows.Controls;
using System.IO.IsolatedStorage;
using System.ComponentModel;

namespace IsolatedStorageCrashInBlend
{
    public partial class MyUserControl : UserControl
    {
        public MyUserControl()
        {
            InitializeComponent();

            // 디자인 모드일 때에는 임의의 값 출력
            if (DesignerProperties.GetIsInDesignMode(this) == true)
            {
                Output.Text = Guid.NewGuid().ToString();
            }
            else
            {
                // 디자인 모드가 아닐 경우에만 처리
                // 설정을 읽어 Output에 출력
                if (IsolatedStorageSettings.ApplicationSettings.Contains("LastGuid"))
                {
                    Output.Text = IsolatedStorageSettings.ApplicationSettings["LastGuid"].ToString();
                }
                else
                {   // 설정이 없으면 새 값을 저장
                    IsolatedStorageSettings.ApplicationSettings["LastGuid"] = Guid.NewGuid().ToString();
                }
            }
        }
    }
}

잘 나오죠? 하지만 위의 코드는 좋은 패턴이 아니에요. 약간만 리팩터링을 해보죠.

using System;
using System.Windows.Controls;
using System.IO.IsolatedStorage;
using System.ComponentModel;

namespace IsolatedStorageCrashInBlend
{
    public partial class MyUserControl : UserControl
    {
        public MyUserControl()
        {
            InitializeComponent();

            // 디자인 모드일 때에는 임의의 값 출력
            if (DesignerProperties.GetIsInDesignMode(this) == true)
            {
                Output.Text = Guid.NewGuid().ToString();
            }
            else
            {
                // 디자인 모드가 아닐 경우에만 처리
                InitializeApplicationData();
            }
        }

        private void InitializeApplicationData()
        {
            // 설정을 읽어 Output에 출력
            if (IsolatedStorageSettings.ApplicationSettings.Contains("LastGuid"))
            {
                Output.Text = IsolatedStorageSettings.ApplicationSettings["LastGuid"].ToString();
            }
            else
            {   // 설정이 없으면 새 값을 저장
                IsolatedStorageSettings.ApplicationSettings["LastGuid"] = Guid.NewGuid().ToString();
            }
        }
    }
}

네, 다른 모든 코드도 마찬가지지만 특히 IsolatedStorage와 관련된 코드는 별도의 코드 블럭으로 빼주는 것이 좋아요.
아니, 반드시 그렇게 해야 해요.
이 외에도 블렌드에서만 발생하는 문제가 가끔 있는데요, 그 문제가 코드와 연관된 것이라면 DesiginerProperties를 사용하여 회피할 수 있어요.

샘플을 첨부했으니 한 번 이렇게 저렇게 테스트 해 보세요.


저작자 표시 동일 조건 변경 허락
신고
Posted by gongdo

컴퍼넌트 및 컨트롤 개발자/디자이너에게 반드시 필요한 기능이죠. 보통 우리가 컨트롤을 디자인 할 때에는 특히, 데이터 바인딩을 사용하는 컨트롤의 경우에는 실제 데이터가 표시될 자리에는 아직 아무런 데이터가 들어가지 않았기 때문에 디자이너들이 그 곳에 임의의 값이 어떤 형태로 들어갈지 알 수 없다는 문제점이 있죠. 바로 이럴 때 System.ComponentModel.DesignerProperties 클래스를 유용하게 사용할 수 있어요.

우선 샘플 프로젝트부터 받아 보시죠.

먼저 간단하게 유저 컨트롤을 하나 만들어서 테스트 해 보죠. 컨트롤의 이름은 MyUserControl이라고 하고 크기는 100x100으로 아무것도 없는 컨트롤이에요. 그리고 코드 비하인드에 다음과 같이 간단한 코드를 넣어보죠.

public MyUserControl()
{
    InitializeComponent();
    TextBlock tb = new TextBlock();

    if (DesignerProperties.GetIsInDesignMode(this) == true)
    {
        // Design-time
        LayoutRoot.Background = new SolidColorBrush(Colors.Blue);
        tb.Text = "in Design";
    }
    else
    {
        // Run-time
        LayoutRoot.Background = new SolidColorBrush(Colors.Green);
        tb.Text = "in Runtime";
    }

    LayoutRoot.Children.Add(tb);
}

DesignerProperties.GetIsInDesignMode() 메서드는 주어진 UIElement가 현재 디자인 모드에서 렌더링 되고 있는지 여부를 반환해요. 해당 UIElement가 디자인 모드 즉, Blend에서 렌더링 되고 있다면 true를, 웹브라우저 등에서 렌더링 되고 있다면 false를 반환하는거죠.

위의 코드는 컨트롤이 인스턴스화 될 때 디자인 모드에서는 파란색으로 컨트롤을 채우고 "in Design"이란 문자열을 출력하고 런타임에서는 녹색으로 컨트롤을 채우고 "in Runtime"이란 문자열을 출력하도록 작성되었어요.

비주얼 스튜디오에서 MyUserControl을 볼까요?

아무것도 안나오죠? 이것은 비주얼 스튜디오의 XAML 뷰어(코드명 사이더)는 해당 UserControl을 새로 생성하는 것이 아니라 단지 XAML을 분석하여 보여준다는 것을 알 수 있죠.

블렌드의 경우도 마찬가지에요.

 

자, 다음으로 MyUserControl을 XAML에서 추가하여 사용하는 Page.xaml을 한번 볼까요?

비주얼 스튜디오의 XAML 뷰어에서는 디자인 모드가 아닌 런타임으로 판단하는군요. 이것은 아마도 버그내지는 잘못된 판단이 아닐까 싶어요. 아무리 사이더에서 실제로 디자인 하는게 불가능하더라도 엄연히 이 시점은 '디자인'상태니까요.

반면, 블렌드에서는 디자인 모드를 정상적으로 인식하는 것을 볼 수 있죠.

그렇다면 브라우저에서는? 당연히 런타임으로 나오겠죠?

 

DesignerProperties 클래스가 유용하게 쓰이는 경우는 앞에서 말했던 것처럼 동적으로 변경되는 값의 샘플 값을 디자이너에게 보여주고 싶을 때인데요 이 외에도 이 클래스를 반드시 써야 하는 경우도 있어요. 바로 몇몇 코드는 블렌드에서 처리할 수 없어서 에러를 발생시키는 원인이 되기도 해요.

이렇게 말이죠. 이게 당해보면 진짜 환장할 노릇이거든요. 왜냐면 유저 컨트롤 그 자체에서는 잘 보이는데 그 컨트롤을 사용한 다른 컨트롤의 디자인에서만 안보이니까요.

어떤 경우에 위와 같은 에러가 나오는지 완전히 정리되지는 않았지만 한가지 확실한 것은 IsolatedStorage가 사용되었을 때에요. IsolatedStorage를 쓸 때의 주의점과 해결 방법은 다음 포스팅에서 설명할께요.

저작자 표시 동일 조건 변경 허락
신고
Posted by gongdo

실은 추석 전이라 가벼운 마음으로 준비했는데 생각보다 많은 분들이 와주셔서 정말 놀랬어요.

여튼 발표자료를 올립니다. 발표 PT와 데모(UserControl, CustomControl 및 Blend 데모)를 포함하고 있어요.


거의 대부분의 자료 참고를 마이크로소프트의 실버라이트 프로그램 매니저 중 하나인 Karen Corby의 블로그에서 얻을 수 있었고요, 제대로 공부하고 싶다면 꼭 방문해보시길 바래요.

자세한 강좌도 따로 진행하고 싶은데 요즘 프로젝트가 빠듯해서 확신이 안가네요. 어쨌든 기회되는대로 추가적인 정보를 올리도록 하지요.

저작자 표시 동일 조건 변경 허락
신고
Posted by gongdo
실버라이트를 공부하시는 모든 분께, Blend Sep. preview를 지금 당장 설치하실 것을 '명령'합니다. 한가지 주의할 것은 기존 preview는 지우셔야 해요.

사실 Sep. preview가 나온지는 몇 일 되었지만 뭐 얼마나 달라졌겠나 싶어서 그냥 밍기적 거리다가 주말도 되고 해서 잠깐 설치해봤는데... 이거 시쳇말로 하악하악인데요!!

하나씩 추가된 피추어들을 리뷰할께요.

1. 깔끔하게 정리된 프로젝트 종류

보시다시피 .NET버전과 .NET "Orcas"버전으로 나뉘어 있던 프로젝트가 통합되었어요. 솔직히 저도 이 전의 두 프로젝트가 어떤 점에서 차이가 있는지 애매했었는데 환영이죠!

2. Split 뷰 추가

디자이너보다는 개발자에게 희소식. 보통 수정작업 할 때는 Design과 XAML을 왔다갔다 할 일이 많은데 무지 귀찮았죠. 이번엔 Split뷰가 따로 생겨서 작업이 좀 더 쾌적해졌어요.

3. 솔루션 익스플로러 탑재

이 전까지는 하나의 프로젝트 단위로만 로드되었었는데 이제는 솔루션 단위로 로드할 수 있게 되었어요. 한가지 문제점은 '솔루션 폴더'는 인식하지 못하더군요. 매우 아쉽지만 이것은 차기 버전에서 해결되겠죠?

4. 스토리보드를 생성하는 기본값이 'Create as a Resource'로 변경

사실 리소스로 만드는 경우가 훨씬 더 많잖아요? 아주 작은 차이지만 환영할 만한 배려에요.

5. 강력해진 Ease동작, 시각적인 KeySpline 설정

!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
아름답지 아니한가!
KeySpline 곡선을 너무나도 직관적으로 너무나도 쉽고 자연스럽게 만들 수 있어요.
사실 이전에 이런 인터페이스를 만들어볼까 생각하고 있었는데 생각만하고 말기를 정말 잘한 것 같네요^^;

6. 편리해진 스토리보드 복사

작업하다보면 비슷한 스토리보드를 복사할 필요가 있는데요, XAML까지 가서 복사하지 않아도 깔끔하게 블렌드에서 할 수 있게 되었어요.

7. 스토리보드 뒤집기

와우우우우~~~!!!!!

보통 롤오버, 롤아웃 애니메이션은 대부분 서로 역순으로 재생하는게 대부분이죠. 이런 애니메이션을 위해 Reverse 기능이 생겨났어요. 아... 이젠 애니메이션 하나하나 시간 계산해서 역순으로 배치할 필요가 없어졌네요. 감격ㅠ.ㅜ

이 외에도 WPF와도 연관된 추가적인 기능들이 있는데 자세한 것은 이곳을 참고하세요.

여튼 생각지도 못하게 좋은 기능들이 대거 추가되었네요. 너무 좋아요!
신고
Posted by gongdo


티스토리 툴바