I posted how to use DataBinding with Behaviors in Silverlight 3 recently. However, it turns out, it's impossible or very limitted.

Follow code is what I expected to work.

<Grid x:Name="LayoutRoot" Background="White">
    <Button Content="Test" HorizontalAlignment="Right">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <hi:ShowMessageBoxAction x:Name="Action1"/>
            </i:EventTrigger>
        </i:Interaction.Triggers

        <i:Interaction.Behaviors>
            <hi:BindingProxyBehavior
                        TargetName="Action1"
                        TargetPropertyName="Message"
                        Binding="{Binding Path=MockString}" />
        </i:Interaction.Behaviors>
    </Button>
</Grid>

[It doesn't work, 'cause Behaviors are not FrameworkElements]

- ShowMessageBoxAction which named "Action1" by x:Name attribute has a property named Message.
- BindingProxyBehavior is a Behavior. And it figures out "Action1" by AssociatedObject(LayoutRoot).FindName method when it has been invoked.

But It's impossible, 'cause Behaviors are not Frameworks so they can't be found by FrameworkElement.FindName method.

It's OK, I can understand why is it impossible. However how do you think about code follow:

<DataTemplate x:Key="DataTemplate1">
    <Grid>
        <Button HorizontalAlignment="Left" Content="{Binding Mode=OneWay, Path=Title}">
            <i:Interaction.Triggers>
                <i:EventTrigger x:Name="Trriger1" 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>
        </Button>
    </Grid>
</DataTemplate>

[Does it work or not?]

It's similar to first one, except root Grid is in the DataTemplate.
Guess what? it works. Very well.
HOW COME!? Isn't it wierd?

Now I have to give up to do DataBinding with Behaviors in Silverlight 3 by that way.
It makes me depressed. "No binding, more work".
Anyway all I really want to ask Microsoft is, just allow us DataBinding with Behaviors, so we can create application rapidly, design-friendly, and even elegantly! Like follow code:

<Grid x:Name="LayoutRoot">
    <Button Content="Test">
        <i:Interaction.Triggers>
            <i:EventTrigger EventName="Click">
                <hi:ShowMessageBoxAction
                    x:Name="Action1"
                    Message="{Binding Path=Description}" />
            </i:EventTrigger>
        </i:Interaction.Triggers>
    </Button>
</Grid>

[Elegant DataBinding with Behaviors]

Here for sample project:

저작자 표시 동일 조건 변경 허락
신고
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

제 메인 PC의 개발 환경이 실버라이트 2로 되어 있어서 자료 정리에 시간이 많이 걸렸네요. 여튼 4월 18일 건국대 새천년 기념관에서 개최된 제 1회 DevDcc 행사에서 발표했던 “실버라이트 3의 등장과 디자인-개발 패러다임의 변화”의 PPT와 데모에요.

데모1에서는 디자이너 이은아님과 함께 처음 실버라이트를 접한 디자이너와 어느 정도 실버라이트 개발에 익숙해진 개발자가 겪을 수 있는 문제점을 다뤄봤어요. 디자이너와 개발자가 서로의 작업을 이해하고 도와주는 것이 역시 유일한 답이겠죠. 또 데모에는 남성 개발자들의 압도적인 지지를 받고 있는 *소녀시대*의 gee 영상으로 카드를 만들어 봤는데요, 아마 데모보다 이쪽에 더 관심 있는 분들이 많지 않을까 하네요 ㅎㅎ.

또한 데모1에서 자세한 설명은 하지 않았지만 Perspective 3D와 데이터 바인딩 그리고 WrapPanel등 실버라이트 3에서 새로 추가되거나 강화된 기능들을 적극적으로 활용하여 만들었으니 어느 정도 참고가 될 거에요.

데모 2에서는 디자이너 장미연님과 함께 했는데요, 장미연님은 현업에서 WPF 프로젝트를 수행하고 있고 개발과 디자인의 중간영역에서 디자이너가 어떤 역할을 해야 하는지에 대해 많은 경험을 가지고 계시죠. 또한 프로젝트 특성상 데이터를 다루는 일이 많은데요, 이 데모를 통해 실버라이트 3 그리고 블렌드 3에서 강화된 데이터 관련 기능을 어떻게 활용하는지 제시하고 있어요.

데모 2에서 개발자는 데이터 원본 생성과 패널 및 컨트롤 코드를 작성하는 임무를 맡고 디자이너는 그 데이터와 컨트롤들을 활용하여 자유롭게 디자인 할 수 있죠. 데모에서 최종적으로는 기존의 딱딱했던 사각형의 리스트박스에서 벗어나 애니메이션 효과와 함께 원형으로 배치되는 패널을 사용하여 데이터를 표시하고 있어요.

데모 3에서는 디자이너 김선구님과 함께 실버라이트 3에서 추가된 가장 강력한 기능 중 하나인 비헤이비어Behaviors에 대해 알아봤는데요, Behaviors는 크게 트리거Trigger & 액션Action과 비헤이비어Behavior로 나눌 수 있어요. Trigger&Action은 어떤 오브젝트에서 이벤트가 발생했을 때 특정 동작을 수행하는 것을 말하고 Behavior는 어떤 오브젝트가 가지는 그 외의 모든 행동 특성을 의미해요. Behaviors는 개발자에게 오브젝트의 행동을 모듈 단위로 설계하도록 도와주고 디자이너에게는 이 Behaviors를 사용하여 개발자의 도움 없이도 멋진 인터랙션을 가지는 애플리케이션을 디자인 할 수 있어요.

데모 3에서는 Behaviors의 활용을 극대화 하여 심지어 물리엔진 조차도 아주 간단하게 사용할 수 있는 방법을 제시하는데요, 저는 Behaviors의 개념이 앞으로 애플리케이션의 개발 패러다임을 확 바꿀 수 있다고 확신해요.

발표 자료가 이미지 중심으로 이루어져 있어서 자세한 설명은 동영상으로 보는 게 좋을 텐데요, 아쉽게도 아직 동영상 자료의 인코딩과 편집이 덜 끝났어요. 동영상이 업데이트 되면 블로그에 업데이트 할게요.

다시 한번 DevDcc 행사에 참가해주신 여러분께 감사 드립니다. ^^/

저작자 표시
신고
Posted by gongdo

이 전 글에서 실버라이트 3에서 추가된 슈퍼 쿨한 기능 중 하나인 Behavior를 실버라이트 2에서도 구현할 수 있다고 살짝 언급했는데요, 어떻게 구현했는지 소개할께요. 소개에 앞서서 Behavior와 관련된 라이브러리 코드들은 모두 블렌드 3에 포함된 Microsoft.Expression.Interactivity 어셈블리를 리버스엔지니어링으로 카피한거에요. 사용시 참고하시길 바래요.

먼저 동작 완구 부터…http://shiverlight.net/sample/SilverlightInteractivity/


 

뭐어… 특별할 게 없어죠? 이 정도 기능이야 뚝딱뚝딱 코딩하면 10분도 안걸릴거에요. 그렇지만 여기 있는 모든 동작은 코딩이 단 한줄도 들어가지 않은 즉, 순수하게 XAML에서 Behavior와 Trigger만 사용한 거죠.

[샘플 코드]

그럼 구현 과정을 알아보죠.

1. Microsoft.Expression.Interactivity 어셈블리 복사

먼저 실버라이트 3 개발 머신에 블렌드 3를 설치하면 C:\Program Files (x86)\Microsoft Expression\Blend 3 Preview\Libraries\Silverlight 폴더에 Microsoft.Expression.Interactivity.dll 어셈블리가 있는데요, 이것이 바로 Behavior와 Trigger를 지원하기 위한 기반 클래스들을 담고 있죠. 이 파일을 실버라이트 2 개발 머신에 복사해두세요.

2. 리버스 엔지니어링

Microsoft.Expression.Interactivity 어셈블리를 Reflector등으로 까서 코드를 봅니다. 그리고 실버라이트 2 라이브러리 프로젝트를 하나 만들어서 거기에 옮기면 끝.

단, 여기에서 주의할 점이 있는데요, 블렌드의 희한한 이름 제한때문에 라이브러리 프로젝트의 이름은 반드시 Microsoft.Expression.Interactivity가 아닌 다른 이름을 써야 해요. 물론 코드에서 정의하는 네임스페이스의 이름은 아무거나 관계 없어요. 전 HugeFlow.Interactivity라는 이름을 붙여봤어요.

3. Behavior와 Action 만들기복사하기

Microsoft.Expression.Interactivity에는 Behavior와 Action을 위한 기반 클래스만 준비만 되어 있을 뿐, 실제로 동작하는 건 없어요. 제대로 동작하는지 확인하려면 만들어 줄 필요가 있는데요, Expression 갤러리에 보면 Microsoft의 Kirupa가 공개한 Sample Silverlight 3 Behaviors 라이브러리가 있어요. 당연히 이것은 실버라이트 3를 위해 만든 라이브러리이지만 Microsoft.Expression.Interactivity를 기반으로 하므로 우리가 리버스 엔지니어링 한 라이브러리와 호환이 돼요. 여튼 이 라이브러리를 다운 받아서 실버라이트 2 라이브러리 프로젝트로 만들어주면 준비는 끝.

4. 블렌드 3에서 테스트 프로젝트 만들기

이제 동작 완구에서 보이는 것처럼 코드를 짜기만 하면 되죠. 그렇지만 단순히 XAML로 이 모든 걸 작성하기엔 좀 귀찮은 생각이 들죠? 문법도 헤깔리고요. 당연히 XAML 디자인은 블렌드에서 하는 게 기본이에요. 그러나 블렌드2는 블렌드3처럼 Behavior나 Trigger와 관련된 기능을 지원하지 않아요. 그렇다면? 그냥 블렌드 3를 써서 디자인 하는거죠.

5. 블렌드 3에서 만들어진 XAML을 실버라이트 2 프로젝트로 복사하기

블렌드 3로 디자이너가 Behavior와 Action을 사용하여 이것저것 디자인한 후 만들어진 XAML을 그대로 실버라이트 2 프로젝트로 복사하세요. 그리고 XAML의 xmlns에서 Microsoft.Expression.Interaction 부분만 우리가 리버스 엔지니어링 한 라이브러리로 바꿔주면 끝.

하나하나 과정을 보일까 하다가 별로 중요한 작업은 아니라 결과물만 첨부했어요.

 

이렇게 만든 Interactivity 라이브러리의 장점으로는

  • 블렌드 3에서 Behavior와 Action 기능을 사용한 디자인을 그대로 복사하여 사용할 수 있다.
  • 블렌드 2에서도 디자인이 깨지지 않고 보인다.
  • 실버라이트 2 개발 환경에서도 아무 문제 없이 동작한다.
  • 실버라이트 2의 지저분한 코딩을 XAML로 수용할 수 있게 한다.
  • 가볍다. Interactivity 라이브러리의 용량은 겨우 36.5kb로 실제로 위의 샘플 애플리케이션의 XAP 파일은 33.3kb, 최적화하면 26.6kb밖에 안된다.

반면 물론 주의 할 점도 있어요.

  • 리버스 엔지니어링한 것으로 일단은 불법이다.
    (그렇지만 별로 문제 될 것 같지는 않습니다만… –_-)
  • 당연하지만 Behavior나 Action외의 ElementBinding이나 Effect와 같은 기능은 지원하지 않는다.

그 외엔 딱히 단점을 찾기 어렵네요^^

암튼, 실버라이트 3의 강화된 기능 중 일부는 이처럼 실버라이트 2에서 당장 사용할 수 있어요. 현업 개발자들은 실버라이트 3가 정식으로 릴리즈 될 때까지는 이런 방법을 적극적으로 활용하는 것도 좋을 거에요.

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


티스토리 툴바