GSI

사용자 삽입 이미지

본 프로그램은 위의 그림의 Grid 객체가 중앙을 기준으로 회전하는 에니메이션 예제 입니다.
Start Angle, End Angle의 값을 변경해서 시작과 끝의 각도를 정해줄 수 있습니다.
Start, End의 회전각도를 정하고 Start 버튼을 누르면 원하는 각도만큼 회전할 수 있습니다.

본 예제는 Animation을 진행할 때 Value의 객체를 cs 파일에서 접근해서 처리 하기가 힘든 기존의 부분을 처리 하기 쉽도록 테스트를 해본 겁니다. ^^ (개인적으로 힘들었어요)

[코드 설명]
Animation의 SplineDoubleKeyFrame에 들어 가는 Value의 값을 바꾸기 위해서
처리용 클래스를 하나 제작했습니다.

    public class AniControl
    {
        private int start;
        private int end;

        public int Start
        {
            set { start = value; }
            get { return start; }
        }

        public int End
        {
            set { end = value; }
            get { return end; }
        }
    }

이제 연동을 위해서 xaml 코드에 추가작업을 했습니다.

xmlns:src="clr-namespace:CircleRotate" <-- 네임스페이스를 <Window.. 여기에 추가했습니다.

Window.Resources 내부에 미리 값을 지정하면서 aniControl을 하나 제작생성했습니다.

<src:AniControl x:Key="aniControl" Start="10" End="180" />

미리 제작한 Timeline1의 에니메이션 코드의 SplineDoubleKeyFrame 의 Value에 DataBind를 연결합니다.

<Storyboard x:Key="Timeline1">
 <DoubleAnimationUsingKeyFrames BeginTime="00:00:00" Storyboard.TargetName="grid" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
        <SplineDoubleKeyFrame KeyTime="00:00:00"
                              Value="{Binding Source={StaticResource aniControl}, Path=Start}"/>
  <SplineDoubleKeyFrame KeyTime="00:00:02"
                              Value="{Binding Source={StaticResource aniControl}, Path=End}"/>
 </DoubleAnimationUsingKeyFrames>
</Storyboard>

이렇게 해서 실행해 보면 객체를 회전시킬 수 있습니다.
여기서 조금더 추가를 해서 Start, End의 값을 TextBox를 통해서 값을 받아서 회전 값을 처리하도록 구현했습니다.
TextBox의 값을 바로 바인딩해도 되지만 aniControl로 값을 보내도록 해봤습니다.

<TextBox HorizontalAlignment="Left" Margin="90,80,0,0" VerticalAlignment="Top" Width="56" Height="24"
         Text="{Binding Source={StaticResource aniControl}, Path=Start, Mode=TwoWay}"
         TextWrapping="Wrap" RenderTransformOrigin="0,0.333" x:Name="txtStart"/>
<TextBox HorizontalAlignment="Left" Margin="90,108,0,0" VerticalAlignment="Top" Width="56" Height="24"
         Text="{Binding Source={StaticResource aniControl}, Path=End, Mode=TwoWay}"

자세한 코드 내용은 소스를 한번 보시구요.
모르는거 있으시면 연락 주세요 ^^.

관련 소스 :

Posted by gsi
:

[WPF] ColorScroll Demo

WPF Sample 2007. 11. 27. 13:13 |

ColorScroll

사용자 삽입 이미지

3개의 슬라이드 바를 사용해서 칼라 값을 조정하는 데모 입니다.
MultiBinding을 사용해서 3개의 슬라이드 바의 값을 합쳐서 RGB로 만들어 내는 방법입니다.
여기에는 IValueConverter 를 상속받아서 처리 하는 코드도 같이 포함되어 있습니다.

관련 코드 :

Posted by gsi
:

ProgressBar Demo

WPF Sample 2007. 11. 26. 13:06 |

Gsi ProgressBar Demo

사용자 삽입 이미지

Start 버튼을 누르면 프로그래스바가 100%까지 차는 모양을 도시해봤습니다.

- TextBlock의 값은 IValueConverter 를 사용해서 double의 값을 string형태로 변환했습니다.
- Rectangle을 사용해서 프로그래스바를 하나 작성했습니다.
- Rectangle의 Width의 속성을 사용해서 증가율을 표시 하고
   해당 증가율을 옆에 TextBlock로 하나 작성해서 뿌렸습니다.

바인딩은 Rectangle의 Width를 소스형태로 하고 TextBlock의 Text가 타겟형태로 구성
모드는 디폴트로 처리 했습니다.

관련 소스 :

Posted by gsi
:

GsiClock v0.1

WPF Sample 2007. 11. 22. 14:40 |

GsiClock v0.1


내용 : 시계
코드 기술 :
1. DependencyProperty 를 사용한 의존 프로퍼티 사용
2. DispatcherTimer 를 사용한 타이머 사용

관련 이미지 :
사용자 삽입 이미지
관련 소스 :
Posted by gsi
:

데이터 바인딩#1 - 기본
데이터 바인딩#2 - Binding Mode
데이터바인딩#3 - DataContext
데이터 바인딩#4 - TextBox vs Run
데이터 바인딩#5 - FrameWorkElement Demo
데이터 바인딩#6 - IValueConverter


이번 시간에는 변환에 대해서 알아 보겠습니다. 데이터 바인딩을 하다 보면 간혹 다른 타입의 데이터를 변환해서 사용해야 하는 경우가 발생합니다. 칼라 값을 변환해서 사용한다던지 아니면 실수형 데이터를 정수형 데이터로 변환해서 사용한다던지 하는 과정을 처리 해야 하는데요 이때 사용할 수 있는 것이 IValueConverter 인터페이스 입니다.

변환을 수행하는 클래스를 제작할때 반드시 IValueConverter 인터페이스를 구현해야 합니다.
그 형태는 아래와 같습니다.

public class MyConverter : IValueConverter
{
   public object Convert(object value, Type typeTarget,
                                                  object param, CultureInfo culture)
   {
      ...
   }

   public object ConvertBack(object value, Type typeTarget,
                                                    object param, CultureInfo culture)
   {
      ...
   }
}

value 인자는 변환될 객체이고 typeTarget는 변환될 객체의 타입입니다.
세번재 인자인 param은 Binding할때 ConvertParameter 프로퍼티가 명시한 객체가 들어가게 됩니다. 그리고 마지막 객체는 대부분 무시 됩니다.

그리고 변환을 위해서는 Convert, ConvertBack 두개가 반드시 필요 합니다.

C#에서는 아래와 같이 수행할 수 있습니다.
Binding bind = new Binding(); bind.Convert = new MyConverter();


아래의 코드는 Convert의 내용입니다.

    [ValueConversion(typeof(double), typeof(decimal))]
    class DoubleToDecimalConverter : IValueConverter
    {
        public object Convert(object value, Type typeTarget, object param, CultureInfo culture)
        {
            decimal num = new decimal((double)value);

            if (param != null)
                num = Decimal.Round(num, Int32.Parse(param as string));

            return num;
        }

        public object ConvertBack(object value, Type typeTarget, object param, CultureInfo culture)
        {
            return Decimal.ToDouble((decimal)value);
        }
    }

여기서 보시면 위쪽의 [ValueConversion(typeof(double), typeof(decimal))] 의 내용은 사실상 없어도 에러가 나거나 하지는 않습니다. 하지만 WPF 문서에서 보게 되면 이 구문을 클래스 정의의 바로 밑에 포함하게 권고 하고 있습니다. 제가 봐도 들어가 있을때 가독성 부분에서는 조금더 유연해 지지 않을까 생각 됩니다.

Convert를 xaml 코드에 연동하는 부분은 이전 강좌의 소스 코드 부분에 바로 적용해봤습니다.

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:src="clr-namespace:WpfApplication1"
    Title="Window1" Height="300" Width="300">

    <Window.Resources>
        <src:DoubleToDecimalConverter x:Key="conv" />
    </Window.Resources>

    <StackPanel>
        <ScrollBar  Orientation="Horizontal"
                    Margin="24"
                    Maximum="100"
                    LargeChange="10"
                    SmallChange="1"
                    Value="{Binding ElementName=Simple, Path=Number, Mode=OneWayToSource}" />
       
        <src:SimpleElement x:Name="Simple" HorizontalAlignment="Center" />
       
        <ScrollBar  Name="scroll"
                    Orientation="Horizontal"
                    Margin="24"
                    Maximum="100"
                    LargeChange="10"
                    SmallChange="1"
                    Value="{Binding ElementName=Simple, Path=Number, Mode=OneWay}" Height="17" />
       
        <src:SimpleElement HorizontalAlignment="Center" Number="{Binding ElementName=scroll, Path=Value, Mode=OneWay, Converter={StaticResource conv}, ConverterParameter=2}" Height="50" />
    </StackPanel>
</Window>

xaml 코드에서는 위에서와 같이 Resource에서 IValueConverter를 구현하는 클래스를 명시해 주어야 합니다.
그리고 Binding 정의에서는 위에서와 같이 Converter={StaticResource conv}, ConverterParameter=2 를 해주시게 되면 됩니다.

추가적으로 public의 프로퍼티가 있을 경우 값을 추가한 후에 정보 전달도 가능합니다.
<src:DoubleToDecimalConverter Decimals="4" x:Key="conv" />
(Decimals 라는 public 프로퍼티가 선언되어 있다고 가정할때)

위의 코드의 결과는 이전의 강좌에서 소수점으로 쫙 나열되어 있는 정보를 소수 둘째 자리까지 자른후에 표시 할 수 있는 코드 입니다. ^^

그럼.. 오늘 강좌는 여기까지 ^^..
다음 강좌는 MultiBinding를 작성하도록 하겠습니다.

참고 ^^
본 내용은 "찰스페졸드의 WPF"의 내용을 이해 하고 나름 생각과 같이 정리한 겁니다.
제제가 가해질 경우 바로 삭제하도록 하겠습니다. ^^;
Posted by gsi
:

데이터 바인딩#1 - 기본
데이터 바인딩#2 - Binding Mode
데이터바인딩#3 - DataContext
데이터 바인딩#4 - TextBox vs Run
데이터 바인딩#5 - FrameWorkElement Demo
데이터 바인딩#6 - IValueConverter

저번 시간까지 텍스트에 대해서 알아 봤습니다.
이번 시간은 FrameElement를 사용하게 되면 좋은 효과를 볼 수 있는 데모를 보면서 의존 프로퍼티의 장점을 보도록 하겠습니다.

의존 프로퍼티 시스템은 내부에 통보 장치가 구현되어 있어서 바인딩 소스가 의존 프로퍼티가 될 필요가 없지만 의존 프로퍼티일 경우 상당히 유용해질 수 있습니다.
이 말은 소스가 의존 프로퍼티가 없어도 타겟의 경우 소스의 값을 참조 할 수 있지만, 의존 프로퍼티가 있을 경우 통지 메시지를 받을수 있어서 소스이지만 타깃의 기능을 사용할 수 있다 정도로 이해 하시고 다음 소스를 보시면 더 이해가 빠를 겁니다.

우선  FrameWorkElement 를 상속받은 클래스를 하나 생성합니다.

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Media;

namespace WpfApplication1
{
    class SimpleElement : FrameworkElement
    {
        // DependencyProperty 정의
        public static DependencyProperty NumberProperty;

        // 정적 생성자에 DependencyProperty 생성
        static SimpleElement()
        {
            NumberProperty =
                DependencyProperty.Register("Number", typeof(double),
                    typeof(SimpleElement),
                    new FrameworkPropertyMetadata(0.0,
                        FrameworkPropertyMetadataOptions.AffectsRender));
        }

        // DependencyProperty를 CLR 프로퍼티를 노출
        public double Number
        {
            set { SetValue(NumberProperty, value); }
            get { return (double)GetValue(NumberProperty); }
        }

        // MeasureOverride를 오버라이딩해 크기를 하드 코딩
        protected override Size MeasureOverride(Size availableSize)
        {
            //return base.MeasureOverride(availableSize);
            return new Size(200, 50);
        }

        // Number 프로퍼티를 보여주는 OnRender
        protected override void OnRender(DrawingContext dc)
        {
            dc.DrawText(
                new FormattedText(Number.ToString(),
                    CultureInfo.CurrentCulture, FlowDirection.LeftToRight,
                    new Typeface("Times New Roman"), 12,
                    SystemColors.WindowTextBrush),
                    new Point(0, 0));
        }
    }
}


이 클래스는 double라는 double 타입의 프로퍼티를 하나 정의 했습니다. 이 프로퍼티는 NumberProperty라는 DependencyProperty의 지원을 받게 됩니다.
FrameworkPropertyMetadata 는 초기값이 0 이며, 프로퍼티에 변화가 생기면 OnRender가 호출되고 화면이 갱신 됩니다.

이제 이 코드를 적용할 xaml 코드를 보겠습니다.
<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:src="clr-namespace:WpfApplication1"
    Title="Window1" Height="300" Width="300">
   
    <StackPanel>
        <ScrollBar  Orientation="Horizontal"
                    Margin="24"
                    Maximum="100"
                    LargeChange="10"
                    SmallChange="1"
                    Value="{Binding ElementName=Simple, Path=Number, Mode=OneWayToSource}" />
       
        <src:SimpleElement x:Name="Simple" HorizontalAlignment="Center" />
       
        <ScrollBar  Name="scroll"
                    Orientation="Horizontal"
                    Margin="24"
                    Maximum="100"
                    LargeChange="10"
                    SmallChange="1"
                    Value="{Binding ElementName=Simple, Path=Number, Mode=TwoWay}" />
       
        <src:SimpleElement HorizontalAlignment="Center" Number="{Binding ElementName=scroll, Path=Value, Mode=OneWay}"/>
    </StackPanel>
</Window>

SimpleElement 엘리먼트상의 x:Name 속성은 FrameworkElement를 상속받지 않은 XAML 엘리먼트를 위한 속성이다. 이 엘리먼트들은 Name 프로퍼티가 없기 때문에 Name 프로퍼티를 사용할 경우에는 에러가 발생한다. 이 에러는 "SimpleElement가 동일한 어셈블리에서 구현되었기 때문에 Name 속성 대신에 x:Name 속성을 사용해야함" 이다.

이 내용을 사용해서 행동을 해보면 아래와 같은 행동이 일어 난다.
첫 번째 ScrollBar를 움직이면  나머지 모든 정보가 바뀌게 된다.
두 번째 ScrollBar를 움직이면 첫 번째 ScrollBar는 움직이지 않는다.

사용자 삽입 이미지


첫 번째 ScrollBar는 OneWayToSource로 되어 있기 때문에 ScrollBar가 타깃이 되지만 내부적으로는 소스형태가 되는 것이다. 이전 강좌에서 말한 것처름 타깃이 소스로 날아 가는거라고 했다. 즉, ScrollBar의 값이 SimpleElement로 전달 되게 되는 것이다. 이것은 SimpleElement가 의존 프로퍼티의 형태를 뛰지 않았을때를 가정한다.

두 번째 ScrollBar는 TwoWay 형태를 취하고 있기 때문에 Element 로 값을 업데이트 하게 된다. x:Name 를 가지고 있는 SimpleEment로도 값을 보내게 되는 것이다.

설명은 여기 까지며 덫붙여 설명하면,

SimpleElement() 에 포함되어 있는 FrameworkPropertyMetadataOptions 의 옵션에는 데이터 바인딩을 처리해 줄 수 있는 옵션들이 포함되어 있다.

두 번째 ScrollBar의 Mode=OneWay를 하게 되면 첫 번째 ScrollBar와 연동되지 않으며,
첫번째 SimpleElement와도 연동되지 않는다.
OneWay로 하게 되면 위쪽의 SimpleEment의 값을 타깃으로 받을 수만 있고 넘겨 줄 수가 없게 되는 것이다.

이번 강좌는 여기까지 ^^.
OneWay, TwoWay, OneWayToSource에 대해서 조금은 더 테스트를 해보면서
확실하게 알아갈 필요가 있는듯 합니다.
FrameWorkElement의 이용에 대해서도 한번더 이해를 할 수 있는 시간이였습니다.

모두 수고 ^^

참고 ^^
본 내용은 "찰스페졸드의 WPF"의 내용을 이해 하고 나름 생각과 같이 정리한 겁니다.
제제가 가해질 경우 바로 삭제하도록 하겠습니다. ^^;
Posted by gsi
:

WPF Healthcare Demo

WPF 2007. 11. 21. 09:40 |

Friday, February 16

Impress your friends showcasing WPF

Copie d'écrande l'application WPF Patient monitoringYou surely already have seen demonstrations of the applications which can be made using Windows Presentation Foundation (formerly Avalon). At events like the Ready For a New Day Launch, for instance.

Among those, did you see that impressive healthcare monitoring application with pages rotating in 3D? Well, it's available now, together with its source code. It runs on Windows Vista, but also on Windows XP (provided you install the .net framework 3.0). Just download it there, and run it (it's already compiled).

Unzip it, go to the Healthcare_Prototype\sources\Avalon Patient Monitoring\bin\Release directory and double click Avalon Patient Monitoring.exe. And impress your friends.

From a technical standpoint: what's impressive is not as much the result (such applications could be made before WPF) as the fact this kind of applications can be created easily, quickly and in an elegant way with WPF. In the ZIP file you'll get, there's a PowerPoint document explaining what's behind the application.

Posted by gsi
:

데이터 바인딩#1 - 기본
데이터 바인딩#2 - Binding Mode
데이터바인딩#3 - DataContext
▶데이터 바인딩#4 - TextBox vs Run
데이터 바인딩#5 - FrameWorkElement Demo
데이터 바인딩#6 - IValueConverter


소스 정보를 사용해서 타겟에 적용할때 텍스트로 원하는 형태의 문자열로 만들어서 하고 싶을때가 있다.
아래의 예제를 보자.

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Title="Window1" Height="300" Width="300" Name="window">

    <StackPanel Orientation="Horizontal"
                HorizontalAlignment="Center" VerticalAlignment="Center"
                DataContext="{Binding ElementName=scroll}" Name="stackpanel">
        <TextBlock Text="{Binding ElementName=window, Path=ActualWidth}" />
        <TextBlock Text=" &#x00D7;" />
        <TextBlock Text="{Binding ElementName=window, Path=ActualHeight}" />
        <TextBlock Text=" Device independent units"/>
    </StackPanel>

</Window>

실행해 보면 300 x 300 device independent units 라는 글자를 볼 수 있다.
TextBlock를 여러개 써서 하는거 자체가 조금 어울리지 않아 보인다. 그래서 Run 을 사용하는 코드를 적용하게 되면 조금더 코드가 깔끔해지게 된다.

아래의 코드는 TextBlock로 이루어진 부분을 Run으로 처리한 내용이다.

        <TextBlock>
            <Run Text="{Binding ElementName=window, Path=ActualWidth}" />
            <Run Text=" &#x00D7;" />
            <Run Text="{Binding ElementName=window, Path=ActualHeight}" />
            <Run Text=" Device independent units" />
        </TextBlock>

하지만 이 코드를 쓰게 되면 아래와 같은 에러 코드를 보게 된다.
Error 1 A 'Binding' cannot be set on the 'Text' property of type 'Run'. A 'Binding' can only be set on a DependencyProperty of a DependencyObject. D:\temp4\WpfApplication1\WpfApplication1\Window1.xaml 15 24 WpfApplication1

이 에러가 나는 이유는 TextBlock에 정의된 Text 프로퍼티는 TextProperty라는 의존 프로퍼티에 의해 지원되지만 Run에는 정의 되어 있지 않아서 있다.
즉, 이 이유는 데이터 바인딩의 타깃은 반드시 의존 프로퍼티가 되어야 하는 것이 이유이다.

의존 프로퍼티를 적용한 가장큰 이점은 데이터 바인딩이며, 의존 프로퍼티 시스템은 내부에 통보 장치가 구현되어 있다는 것이다. 바인딩 소스가 의존 프로퍼티가 될 필요는 없지만 의존 프로퍼티일 경우에 유리한 상황이 되는 것이다.

FrameworkElement를 상속 받아서 작성한 clr 객체가 DependencyProperty를 정의 하게 되면서 데이터 바인딩 통지 메시지를 받는 예제를 보여 드리겠습니다.

참고 ^^
본 내용은 "찰스페졸드의 WPF"의 내용을 이해 하고 나름 생각과 같이 정리한 겁니다.
제제가 가해질 경우 바로 삭제하도록 하겠습니다. ^^;
Posted by gsi
:

데이터 바인딩#1 - 기본
데이터 바인딩#2 - Binding Mode
▶데이터바인딩#3 - DataContext
데이터 바인딩#4 - TextBox vs Run
데이터 바인딩#5 - FrameWorkElement Demo
데이터 바인딩#6 - IValueConverter

바인딩 소스 객체를 다른 방법인 FrameworkElement 에 정의된 DataContext를 사용했다.

    <StackPanel >
        <ScrollBar Name="scroll" Orientation="Horizontal" Margin="24"
                    Minimum="1" Maximum="100"
                    LargeChange="10" SmallChange="1" />
        <Label HorizontalAlignment="Center"
                    DataContext="{Binding ElementName=scroll}"
                    Content="{Binding Path=Value}" />
    </StackPanel>

기존의 Label에
Content="{Binding ElementName=scroll, Path=Value}"로 작성했다면,
위의 코드는 DataContext로 분리 되어 두개로 구성되어 있다.
하지만 Datacontext로 했다고 해서 특별히 달라지는 건 없다. 그런데 DataContext가 유용할 때가 있다. 즉, DataContext는 엘리먼트 트리를 통해 상속된다는 것이다. 하나의 엘리먼트에 DataContext를 사용해서 바인딩을 설정하고 자식 엘리먼트에 동일하게 적용되게 되기 때문이다.

아래의 예제를 보자.

    <StackPanel DataContext="{Binding ElementName=scroll}">
        <ScrollBar Name="scroll" Orientation="Horizontal" Margin="24"
                    Minimum="1" Maximum="100"
                    LargeChange="10" SmallChange="1" />
        <Label HorizontalAlignment="Center"
                    Content="{Binding Path=Value, Mode=OneWay}" />
        <Button HorizontalAlignment="Center" Margin="24"
                FontSize="{Binding Path=Value, Mode=OneWay}">
            Son Byoung Uk
        </Button>
    </StackPanel>

사용자 삽입 이미지

DataContext는 StackPanel에 한번 설정되고 Label과 Button은 ScrollBar와 바운딩 되었습니다. ScrollBar를 움직이면 Label의 값이 바뀌고 Button의 FontSize와 바인딩 되면서 글자 크기가 바뀌는 것을 볼 수 있습니다.

참고 ^^
본 내용은 "찰스페졸드의 WPF"의 내용을 이해 하고 나름 생각과 같이 정리한 겁니다.
제제가 가해질 경우 바로 삭제하도록 하겠습니다. ^^;
Posted by gsi
:

데이터 바인딩#1 - 기본
▶데이터 바인딩#2 - Binding Mode
데이터바인딩#3 - DataContext
데이터 바인딩#4 - TextBox vs Run
데이터 바인딩#5 - FrameWorkElement Demo
데이터 바인딩#6 - IValueConverter


Binding 정의가 있는 컨트롤이나 엘리먼트는 항상 바인딩의 타깃이 된다. 바인딩 타깃은 DependencyObject로부터 상속되며 바인딩이 설정되는 프로퍼티는 반드시 의존 프로퍼티의 지원을 받아야 한다.
그래서 Label인 경우 DenpendencyObject 타입의 정적 publid필드인 ContentProperty가 존재 하게 된다. (내부적으로 ^^)

바인딩의 코드를 C#에서 처리한 예제를 보면 알 수 있다.

ScrollBar > scroll
Label > lbl
이라고 가정한다.

Binding bind = new Binding();
bind.Source = scroll;
bind.Path = new PropertyPath(ScrollBar.ValueProperty);
lbl.SetBinding(Label.content, bind);

여기서 바인딩 타깃은 SetBinding의 메소드를 통해서 호출되게 된다. 이 메소드는 FrameworkElement에서 정의 되었고 DependencyProperty인자를 알수 있습니다.

이제 바인딩에 사용되는 Mode에 대해서 살펴 보겠습니다.
바인딩의 Mode를 보게 되면, OneWay, TwoWay, OneTime, OneWayToSource로 나열할 수 있습니다.

기본적인 형태는 아래와 같습니다.

Content="{Binding ElementName=scroll, Path=Value, Mode=OneWay}"

여기서 Mode 프로퍼티를 설정하는 것은 Path 프로퍼티를 설정하는 것과 같이 콤마로 구분됩니다.

Content="{Binding ElementName=scroll, Path=Value, Mode=TwoWay}"

이전의 코드에서 보게 되면 OneWay, TwoWay 는 동일하지만 실제로는 Label의 Content 프로퍼티의 변화도 ScrollBar의 Value프로퍼티에 반영됩니다.

Content="{Binding ElementName=scroll, Path=Value, Mode=OneTime}"

OneTime 모드의 경우는 타깃이 소스로부터 초기화는 되지만 소스의 변화에 반응하지 않습니다. 즉, 한번만 초기화 되고 더이상 되지 않습니다.

Content="{Binding ElementName=scroll, Path=Value, Mode=OneWayToSource}"

이것은 일반적으로 소스와 타깃의 의미에 반대 되는 행동을 하게 됩니다. 다시 말해서 과녁이 화살을 향해서 간 다음에 꽂히는 것과 같습니다.
이 경우는 타깃은 소스를 갱신하게 되는데요. 이전의 코드에서는 Label은 ScrollBar에 건네줄 숫자 형태의 데이터가 없기 때문에 Label은 비어 있고 ScrollBar를 움직여도 반응이 없게 됩니다.

하지만 OneWayToSource가 유용할 때가 있습니다. 바로 두 프로퍼티를 바인딩할 때 타깃 프로퍼티가 의존 프로퍼티의 지원을 받지 못하지만 소스는 지원받는 경우라면 소스에 바인딩을 걸고 Mode를 OneWayToSource로 설정하는 것으로 해결할 수 있습니다.
아래의 소스를 보시면 알 수 있습니다.

    <StackPanel>
        <ScrollBar Orientation="Horizontal" Margin="24"
                Maximum="100" LargeChange="10" SmallChange="1"
                Value="{Binding ElementName=lbl, Path=Content}"/>
        <Label Name="lbl" Content="50" HorizontalAlignment="Center" />
    </StackPanel>

사용자 삽입 이미지

위의 코드가 되면 Label은 소스가 되고 ScrollBar는 타깃이 되게 됩니다.
Label은 50으로 Content를 설정하였고, ScrollBar는 가운데 있게 됩니다. ScrollBar를 움직이면 Label도 같이 움직이는 것을 알 수 있습니다. 이 부분은 Mode가 기본적으로 TwoWay로 설정되어 있기 때문입니다.
하지만 TwoWay를 OneWay 또는 OneTime 로 하게 되면 동작하지 않습니다.

조금 다르게 아래의 코드를 봅시다.

Value="{Binding ElementName=lbl, Path=Content, Mode=OneWayToSource}"

모드는 OneWayToSource로 하게 되면 ScrollBar가 Label 소스를 제어 하게 됩니다. Label은 ScrollBar의 Value을 사용해서 50이 0으로 초기화가 되며ScrollBar를 움직이면 Label이 움직이게 되는 것을 확인할 수 있습니다.

기본 바인딩 Mode는 바인딩이 정의되어 있는 곳의 프로퍼티에 의해 제어되게 된다. ScrollBar에서  Value 프로퍼티의 기본값이 TwoWay 바인딩 모드로 설정되어 있어야 한다.
ScrollBar의 의존 프로퍼티인 ValueProperty는 BindsTwoWayByDefault 프로퍼티가 true인 FrameworkPropertyMetadata가 필요하게 되는 것이다. (이것은 속에 있나 봅니다. ^^)

Mode 프로퍼티는 바인딩의 가장 중요한 컴포넌트 중의 하나입니다. 알맞는 Mode를 설정하는 것이 중요합니다. ^^

참고 ^^
본 내용은 "찰스페졸드의 WPF"의 내용을 이해 하고 나름 생각과 같이 정리한 겁니다.
제제가 가해질 경우 바로 삭제하도록 하겠습니다. ^^;
Posted by gsi
:

Blend를 사용해서 Animation을 작성하다 보면 Blend에서 작성한 코드만 가지고 안될때가 많다. 코드 중간 중간 실시간적으로 받은 데이터의 값을 에니메이션 Value에 추가해서 사용해야 할때가 많아 진다.

이럴 경우 코드 비하인드에서 스토리 보드 부터 다 짜게 되면야.
값 접근하는게 어렵지는 않다. 하지만 에니메이션 정보를 코드로 다 짜준다는건 캐 노가다거나 거의 비효율적인 작업이 될 것이다. 그래서 몇가지 예제를 찾아 봤는데.

다른 방법이 하나 있긴 하다 공도님 사이트에서 본것 ^^..
이것 > http://gongdo.tistory.com/110

하지만 그것도 좀 그렇다. 왠지 작업량이 복잡해 지고 불편하다.

그래서 내부 구조를 조금씩 보면서 아래와 같은 접근 방법을 사용하였다.

<Storyboard x:Key="Timeline1">
 <DoubleAnimationUsingKeyFrames x:Name="TestAni1" BeginTime="00:00:00" Storyboard.TargetName="rectangle" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[3].(TranslateTransform.X)">
  <SplineDoubleKeyFrame x:Name="TestSpline1" KeyTime="00:00:00" Value="0"/>
  <SplineDoubleKeyFrame x:Name="TestSpline2" KeyTime="00:00:01" Value="192"/>
 </DoubleAnimationUsingKeyFrames>
 <DoubleAnimationUsingKeyFrames x:Name="TestAni2" BeginTime="00:00:00" Storyboard.TargetName="rectangle" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[2].(RotateTransform.Angle)">
  <SplineDoubleKeyFrame x:Name="TestSpline3" KeyTime="00:00:00" Value="0"/>
  <SplineDoubleKeyFrame x:Name="TestSpline4" KeyTime="00:00:01" Value="62.206"/>
 </DoubleAnimationUsingKeyFrames>
</Storyboard>

위의 코드도 결국 cs 파일에서 하는거 처름 다 추가 되는거라고 생각하고.
아래와 같이 분해 해보았다.

이런 XAML 코드가 있다고 하고 192라는 값을 코드 중간에 바꾸고자 할때
아래와 같이 하면 접근이 되는 것을 확인 하였다.

// 스토리 보드를 가져 온다.
Storyboard st = (Storyboard)this.FindResource("Timeline1");
// 스토리 보드의 내부 타임 라인 그룹정보를 가져 온다.
TimelineCollection tgroup = (TimelineCollection)st.Children;
// TimelineCollection 안에 있는 객체 하나를 가져 온다.
// 근데 여기서 int형 배열 정보만 받는다. 그럼 내가 몇번째 것을 제어 하고 싶은지
// 알아야 할거 같다.
DoubleAnimationUsingKeyFrames dAniFrame = (DoubleAnimationUsingKeyFrames)tgroup[0];
// SplineDoubleKeyFrame  정보를 가져 오기 위해서
// DoubleKeyFrameCollection 의 정보를 가져 온다.
DoubleKeyFrameCollection dAniFrameGroup = (DoubleKeyFrameCollection)dAniFrame.KeyFrames;
// SplineDoubleKeyFrame  정보를 가져 온다.
SplineDoubleKeyFrame spAniFrame = (SplineDoubleKeyFrame)dAniFrameGroup[1];
// Value 값을 조정할 수 있게 된다.
spAniFrame.Value = 500;

코드 량은 좀 되는거 같아도 접근을 할 수 있는거 같은데요.
사실 이거 말고 다른게 있을듯도 한데.. ms가 이거 만들면서 이런거 고민했을텐데.
사실 다른건 아직 방법을 찾지 못했네요.

혹시 아시면 코멘트 부탁해요.

Posted by gsi
:

출처 : http://xamlxaml.com/2006/08/04/unique-interfaces-in-wpfxaml/

PostItBoard Demo


이런 느낌의 사진 게시판은 느낌이 좋을거 같다.
카테고리별로 나누고 새로운 사진들은 바람에 흔들거린다던지 하는 효과도 좋은거 같다.

누르면 크게 보여 주고 다시 사라지고 하는 효과도 좋을거 같고
포스트잇을 연상케 하는 이 디자인은 나름 멋진듯 하네.

Posted by gsi
:

Win Form 만으로는 WPF 만큼의 효과를 구사하지 못한다.
그래서 생각한게 Custom Control 형태를 취하게 하면서 WPF 컨트를을 Win Form에
연동이 가능하다는 것을 알게 되었다.

즉, Visual Studio 2008에 있는 ElementHost를 선택해서 Form에 추가 합니다.

사용자 삽입 이미지





이후에 화면은 아래와 같으며, References에 windowBase, WindowsFormsIntegration이 추가 됩니다.
사용자 삽입 이미지

하지만 WPF 관련 xaml 파일이 없기 때문에 위와 같이 아무것도 적용할 수 없습니다.

이후에 xaml 파일을 추가 해야 합니다.
xaml 파일만 추가할 수도 있지만, WPF 어플리케이션을 추가한 후에 Blend로 작업하고,
프로젝트를 추가해서 하는게 더 좋은거 같습니다.

프로젝트 생성 후에 Window1.xaml 파일을 그대로 사용하지는 못하는듯 합니다.
UserControl을 상속 받은 xaml 파일을 사용해야 하기 때문에 파일을 하나 추가합니다.

이제 아래와 같은 추가할 수 있는 화면이 나옵니다.
사용자 삽입 이미지


이제 추가 하고 나면 아래의 화면 처름 배치를 할 수 있습니다.
사용자 삽입 이미지











이후의 컨트롤 접근은 다를거 없습니다.
해당 컨트롤.컨트롤이름. 이렇게 진행 됩니다.

궁금한 내용 있으시면.. 코멘트 부탁해요 ^^

Posted by gsi
:

이전에도 소스를 여기에 올린적이 있는듯 하다.
Tool3D 라이브러리를 사용해서 적용하는 3D의 효과를 어떻게 구현할지 이것을 가지고 생각을 해보자.

[관련 이미지]

사용자 삽입 이미지

Cube에 InteractiveMesh 적용 예





















[관련 소스]

Posted by gsi
:

WPF 이미지 표시하기

WPF 2007. 10. 5. 09:44 |

WPF 에서 이미지 표시하기

BitmapImage 는 XAML 로딩을 위해 최적화된 특수한 BitmapSource 이고 Image 컨트롤의  Source로 이미지를 표시하기 쉬운 방법입니다.

이미지 컨트롤 사용하기
Image는 프레임워크 엘리먼트이고 애플리케이션에서 이미지를 표시하는 주된 수단입니다. XAML 에서 Image는 어트리뷰트 문법 또는 프로퍼티 문법의 두 가지 방법으로 사용될 수 있습니다. 다음 예제는 어트리뷰트 문법과 프로퍼티 태그 문법을 모두 사용하여 이미지를 200 픽셀 너비로 그리는 바업ㅂ을 보여줍니다. 어트리뷰트 문법과 프로퍼티 문법의 더 자세한 정보는 Dependency Properties Overview를 참고 하십시오.

XAML
<!-- 간단한 이미지 렌더링. 그러나 이 방법으로 렌더링 하는 것은 애플리케이션 메모리의 사용량에는 좋지 않습니다. 같은 결과를 더 적은 메모리로 생성하는 아래쪽 마크업을 참고 하십시오. -->
<Image Width = "200" Source = "c:\Temp\aaa.jpg"/>

<Image Width = "200">
   <Image.Source>
      <!-- 상당한 애플리케이션 메모리를 아끼기 위해 이미지 소스의 BitmapImage의 DecodePixelWidth나 DecodePixelHeight 값을 원하는 높이와 너비로 설정하십시오. 그렇게 하지 않으면 애플리케이션은 이미지를 화면에 표시될 크기가 아닌 그것의 보통 크기로 렌더링 될 것이라고 생각하고 캐슁될 것입니다.-->
      <BitmapImage DecodePixelWidth = "200" UriSource = "c:\test\aaa.jpg"/>
   </Image.Source>
</Image>

다음 예제는 코드를 사용하여 이미지를 200 픽셀 너비로 그리는 방법을 보여줍니다.

노트 :
BitmapImage는 다중 속성에서 초기화 최적화를 위해 ISupportInitilize 인터페이스를 구현합니다. 속성 변경은 오직 객체 초기화 중에만 발생할 수 있습니다. 초기화가 시작되었음을 알리는 신호로 BeginInit을 호출하고 초기화가 완료되었음을 알리는 신호로 EndInit을 호출합니다. 일단 초기화 되면 속성 변경은 무시됩니다.

C#
// 이미지 엘리먼트 생성
Image myImage = new Image();
myImage.Width = 200;

//소스 생성
BitmapImage myBitmapImage = new BitmapImage();

// BitmapImage.UriSource는 반드시 BeginInit/EndInit 블럭 내에 있어야 합니다.
myBitmapImage.BeginInit();
myBitmapImage.UriSource = new Uri(@"c:\test\aaa.jpg");
myBitmapImage.DecodePixelWidth = 200;
myBitmapImage.EndInit();

//이미지 소스 설정
myImage.Source = myBitmapImage;

Posted by gsi
: