- IsDeferredScrollingEnabled 속성

 : ScrollChanged 이벤트가 scroll이 안정화 되었을 때(즉 ScrollViewer가 정지했을 때) 만 발생하도록 한다.


이 속성의 기본값은 'False' 로 되어 있고, 이를 'True'로 변경하면 위와 같이 동작하게 된다.


프로젝트 중에 ScrollViewer 내부에 수많은 이미지를 보여주도록 하는 경우가 있었는데, 메모리 상의 문제로 화면에 보여지는 영역의 이미지를 로드하고, ScrollChanged 이벤트가 발생할 경우 화면에 보여지는 영역을 다시 계산해서 해당 영역의 이미지를 로드하도록 구현하였다. 이렇게 했더니 스크롤을 이동할 때마다 ScrollChanged 이벤트가 많이 발생해서 퍼포먼스 상의 문제가 있어, IsDeferredScrollingEnabled 속성을 이용해 퍼포먼스를 높인 경험이 있었다.





Adorner
 는 UIElement 위에 정보, 혹은 기능을 표시하기 위해 사용하는 사용자 지정 FrameworkElement 이다.


일반적인 용도

- UIElement 에서 사용자가 크기 조정, 회전, 위치 변경과 같은 기능 핸들 추가

- 다양한 상태를 나타내거나 이벤트에 응답하기 위한 시각적 피드백 제공

- 그 외의 다양한 시각적 효과 overlay

등이 되겠다.


Adorner 는 UIElement 내에 AdornerLayer 라는 레이어를 생성하여 그 위에 Adorner 객체를 위치시키므로 해당 UIElement 내부의 어떤 객체들보다 상위에 나타난다. 따라서 항상 위에 나타나야 하는 객체들 - 상태 정보, 기능 핸들 등은 Adorner 를 사용하는 것이 Z-index 등을 조절하는 것보다 편한 방법이 될 것이다.




Adorner 클래스를 사용하는 방법은 다음과 같다.


1. Adorner 클래스를 상속받아 새로운 클래스를 만든다.

  - Adorner 클래스는 추상 클래스(Abstract Class) 이므로 직접 사용할 수 없다.

  - Rendering 을 구현해야 하는데, 일반적으로 OnRender() 메서드를 오버라이드(override)해서 사용한다.

2. Adorner 를 적용하고자 하는 엘리먼트에 AdornerLayer 를 가져온다.

3. 1에서 생성한 클래스를 2에서 가져온 AdornerLayer 에 추가한다.


  AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(this);

  adornerLayer.Add(myAdorner);


그 외 

- Adorner 는 다른 객체들의 상위에 위치하므로, 마우스 이벤트를 받는다. Adorner 가 마우스 이벤트를 받지 않고 통과시키도록 하려면 IsHitTestVisible 속성을 false로 하면 된다.




MSDN 예시 코드

http://msdn.microsoft.com/ko-kr/library/ms743737.aspx

WPF로 Clipboard 를 사용하여 복사/붙여넣기를 하는 것은 생각보다 매우 간단하다.


System.Windows.Clipboard 클래스 를 사용한다.


1) 복사하기 :

Clipboard.SetText (string text) , Clipboard.SetImage (BitmapSource image) 함수 사용

( 이외에도 SetAudio, SetData, SetDataObject 함수도 존재함)


BitmapImage img = new BitmapImage();

Clipboard.SetImage(img);



2) 붙여넣기 :

Clipboard.GetText(), Clipboard.GetImage(), Clipboard.GetData(), Clipboard.GetDataObject() 등의 함수 사용



BitmapSource source = Clipboard.GetImage();

JpegBitmapEncoder encoder = new JpegBitmapEncoder();

MemoryStream memoryStream = new MemoryStream();


BitmapImage img = new BitmapImage();


encoder.Frames.Add(BitmapFrame.Create(source));

encoder.Save(memoryStream);


img.BeginInit();

img.StreamSource = new MemoryStream(memoryStream.ToArray());

img.EndInit();


memoryStream.Close();


* 사용은 다 비슷비슷하므로 Image 를 예시로 작성해 보았음

이미지를 불러올 경우

가장 간단한 코드는 다음과 같다.


1)

BitmapImage img = new BitmapImage(new Uri(myUri));

Image.Source = img;



검색하다보니 이 코드를 포함해서 여러 개의 코드 조각들 간의

이미지 로딩 속도를 비교한 결과가 있는 블로그가 있었다.

(http://lovehana.com/flyingmt/566?category=8)


위의 블로그에서 가장 속도가 좋다고 나온 코드 조각은 다음과 같다.


2)

BitmapImage img = new BitmapImage();

img.BeginInit();

img.CacheOption = BitmapCacheOption.OnDemand;

img.CreateOptions = BitmapCreateOptions.DelayCreation;

img.DecodePixelWidth = 300;

img.UriSource = new Uri(myUri);

img.EndInit();

Image.Source = img;


단, 2) 번 코드의 문제는 web 상의 이미지는 로드할 수 없다(http:// ... 주소로 된 이미지)





위의 1), 2) 번 코드는 프로세스가 이미지를 사용하고 있어

해당 프로세스나 다른 프로세스에서 해당 이미지를 변경할 수 없다.

즉 이미지를 로드하여 이를 편집하고 덮어쓰기 를 하거나 하는 경우에는 사용할 수 없다.


따라서 이런 경우에는 다음과 같은 코드를 사용한다.


3)

Byte[] buffer;


if (myUri.Substring(0, 4).Equals("http"))

{

    WebClient wc = new WebClient();

    buffer = wc.DownloadData(new Uri(myUri, UriKind.Absolute));

    wc.Dispose();

}

else

{

    buffer = System.IO.File.ReadAllBytes(myUri);

}


MemoryStream ms = new MemoryStream(buffer);

             

BitmapImage img = new BitmapImage();

img.BeginInit();

img.CacheOption = BitmapCacheOption.OnLoad;

img.StreamSource = ms;

img.EndInit();

Image.Source =  img ;


스크롤뷰어를 원하는 지점으로 스크롤시키고자 할 때는

ScrollViewer.ScrollToHorizontalOffset(), ScrollToVerticalOffset() 함수를 사용한다.


원하는 지점까지 스르륵 애니메이션을 적용해서 스크롤시키고 싶은데

위의 함수는 그런 기능을 지원하지 않고,

그렇다면 DoubleAnimation 등의 애니메이션을 사용해야 하는데,


ScrollViewer.HorizontalOffset, ScrollViewer.VerticalOffset 2개의 의존속성은 get 만 지원해서 DoubleAnimation 을 적용할 수 없다.

따라서 스크롤뷰어에서 스크롤 기능에 애니메이션을 적용하려면 스크롤뷰어를 상속받아 별도의 스크롤뷰어를 만드는 방법밖에 없다.


별도의 스크롤뷰어를 만들어 HorizontalOffset, VerticalOffset과 비슷하되 get, set 모두를 지원하는 의존속성을 만들어 이 속성에 애니메이션을 적용하는 방법이다.



과정은 다음과 같다.


1. 새로운 클래스를 선언하고, ScrollViewer 를 상속받도록 선언한다.

  - 예시에서는 'AniScrollViewer' 라고 명명함

2. HorizontalOffset, VerticalOffset 을 대신할 새로운 의존속성을 만든다.

  - 예시에서는 'CurrentVerticalOffset', 'CurrentHorizontalOffset' 라고 명명함

3. 새로 만든 의존 속성이 변경되면 해당 컨트롤의 스크롤이 이동하도록 한다.



4. 기존의 ScrollViewer 를 위에서 만든 새로운 ScrollViewer로 대체하고, 2번에서 만든 의존속성을 사용하여 애니메이션을 적용한다.

  - Animation 객체를 만들고, 해당 애니메이션의 TargetProperty 를 위에서 만든 의존 속성으로 지정한다.

 


다음과 같은 방법으로 스크롤뷰어에 애니메이션을 적용할 수 있다.




Visual Studio 2010을 사용하는 중에, 특정 프로젝트에서 Custom Control(WPF) 를 추가하려고 했으나 리스트에 해당 item 이 나타나지 않았다.


다른 프로젝트에서 아이템을 추가(프로젝트 > 우클릭 - 추가 > 새로운 아이템 > Visual C# items > WPF ) 하면 Window, Page, User Control, Resource Dictionary 등의 8개의 메뉴가 나오는데 해당 프로젝트에서는 아래처럼 User Control 하나만 나왔다.



이유가 혹시 참조를 안했나 해서 확인도 다 해보고, 프로젝트 속성도 검토해보았으나 이유를 찾지 못했는데, 그 해결책은 매우 간단하다.


해당 프로젝트 파일(*.csproj 파일) 을 메모장으로 열어 첫번째 <PropertyGroup> 밑에 다음의 코드를 삽입한다.


<ProjectTypeGuids>{60dc8134-eba5-43b8-bcc9-bb4bc16c2548};{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}</ProjectTypeGuids>


이 부분을 추가하고 다시 프로젝트를 실행시켜 새로운 아이템 추가를 해보았다.


 


다른 프로젝트처럼 8개의 리스트가 모두 추가된 것을 확인할 수 있다.


프로젝트 속성과 관련한 버그인 것으로 보이는데 정확한 이유는 모르겠다.



바인딩을 하는데 있어, 때로는 연산이 필요한 경우가 있다.

예를 들면 바인딩할 때 문자열 뒤에 단위를 붙이고 싶다거나, 또는 bool 값을 Visibility 속성으로(true 일 경우 Visible, false 일 경우 Collapsed 로 각각 변환) 변환하려고 한다던지 할 때 컨버터(Converter)를 사용하면 쉽게 해결할 수 있다.


컨버터는 IValueConverter 를 상속받아 만든다. Convert() 함수와 ConvertBack() 함수를 만들면 되는데, 간단한 예제 코드를 통해 알아보자.


이름에서 알 수 있듯이 Boolean 값을 Visibility 값으로 변경하는 컨버터이다. 변환하고자 하는 로직을 Convert 함수 내부에 구현하고 그 값을 return 해주면 된다.


적용은 다음과 같이 하면 된다.

아래의 코드는 토글버튼(Toggle Button)이 체크되었을 때 해당 DockPanel 엘리먼트의 Visibility 속성을 변경하는 예제이다.

<DockPanel Visibility="{Binding IsChecked, ElementName=myToggleButton, Converter={StaticResource BooleanToVisibilityConverter}}">





의존속성은 기존의 속성을 확장하여 WPF적인 요소를 추가한 속성이라고 할 수 있는데, 

1. code-behind, xaml 측에서 모두 접근 가능

2. 의존속성이 변경되면 그에 맞게 자동으로 렌더링, 로드 등의 처리

의 특징을 갖는다.


기존의 멤버변수와 표현상의 사용법이나 기능은 동일하나 위의 기능을 포함하고 있어 동적으로 변경하는 상황에서 훨씬 강력하고 쉽게 사용할 수 있다.

아래의 사진은 모든 컨트롤들의 기본이 되는 FrameworkElement 클래스의 정의 부분이다.

흔히 많이 사용하는 ActualWidth, ActualHeight 등의 속성들이 의존속성으로 선언되어 있는 것을 확인할 수 있다.

즉 흔히 우리가 사용하는 Width, Height, Background 등의 속성이 사실 다 의존속성이라는 것이다.!




자, 그럼 의존속성은 그냥 "속성, 혹은 멤버변수와 비슷하되 WPF에서 기능을 확장한 특별한 속성이다 !" 라고 이해하고 넘어가서 어떻게 생성하고 사용하는지 알아보자.

1. 의존속성을 선언                    

2. 의존속성을 등록

3. 프로퍼티 생성

위와 같이 생성하면 기존의 다른 의존속성처럼 사용할 수 있다.




+ Recent posts