Element 와 Attribute

XAML 은 XML 기반이기떄문에 element와 attribute를 사용한다. 그러나 element를 닷넷 객체 혹은 구조체와 상응하는 의미로

object element라고 한다. attribute는 property attribute와 event attribute로 구분하며 property attribute는 property로 event attribute는 event로

XML namespace는 CLR 네임스페이스로 각각 맵핑된다.

 

XAML에서 object element를 선언하면 항상 기본 생성자(default contructor) 를 사용해서 상응하는 닷넷 객체를 생성하는 것과 동일하고

property attribute를 설정하는 것도 생성된 닷넷객체에 동일한 프로퍼티를 설정하는 것과 동일하다.

event attribute를 설정하면 객체의 이벤트 처리기와 연결된다.

 

런타임시에 이벤트 처리기는 XAML에서 선언된 객체가 인스턴스화 될때 어떤 프로퍼티보다 먼저 추가된다.

 

Namespace

네임스페이스에 쓰인 schemas.microsoft.com이라는 URL은 임의의 네임스페이스를 구별하기 위한 키워드정도로 생각하면 된다.

XAML 파일의 루트 엘리먼트는 적어도 하나의 XML 네임스페이스가 사용되어야 한다. 

그래야만 자신과 자식 엘리먼트가 적절하게 맵핑된다. 기본 네임스페이스를 추가할때는 적절한 접두어를 사용해야 한다.

ex. xmlns:x = "http://schemas.microsoft.com/winfx/2006/xaml"

 

Property Attribute

ex.

System.Windows.Control.Button b = new System.Windows.Control.Button();

System.Windows.Shapes.Rectangle r = new System.Windows.Shapes.Rectangle();

r.Width = 40;

r.Height = 40;

r.Fill = System.Windows/Media.Brushes.Black;

b.Content = r;

 

XAML에서표현이 다소 길어지는 단점을 감수하고서라도 복잡한 프로퍼티를 설정할수 있는 대안을 제공하는데 그것이 Property Element이다.

프로퍼티 엘리먼트를 사용하면 다음처럼 변경할수 있다

<Button >

<Button.Content>

<Rectangle Height="40" Width="40" Fill="Black">

</Button.Content>

</Button>

C# 코드와 동일한 결과를 얻기 위해서 컨텐트 프로퍼티로 어트리뷰트 대신에 엘리먼트를 사요앻ㅆ다. Button다음의 (.)이 프로퍼티 엘리먼트와 오브젝트 엘리먼트를 구분해준다.

프로퍼티 엘리먼트는 항상 타입명,프로퍼티의 형태로 쓰이며 타입명으로 쓰인 오브젝트 엘리먼트의 내부에 포함되고 자신은 어떤 어트리뷰트도 갖지 않는다.

프로퍼티 엘리먼트는 단순한 프로퍼티로 사용할수도 있다.

ex.<Button Content = "OK" Background="White"/>

이 것을 프로퍼티 엘리먼트로 표현한다면

<Button>

<Button.Content>

OK

</Button.Contetn>

<Button.Background>

Whilte

</Button.Background>

</Button>

 

Type Converter

XAML 파서나 컴파일러는 문자열을 적절한 데이터 타입으로 바꿔주는 타입 컨버터를 찾는다. 모든 타입 컨버터는 TypeConverter 클래스에서 파생된 클래스들이다.

물론, 독자적인 타임컨버터를 만들수도 있다. 타입컨버터는 일반적으로 대소문자 구별하지 않는다.

 

Markup Extension

XAML로 표현할수 있는 범위를 확장해준다. 타입 컨버터와 이것은 보통 런타임시에 주어진 값을 체크해서 문자열에 맞는 적절한 객체를 생성한다.

ex <Button Background = "{x:Null}" Height = "{x:Static SystemParameters.IconHeight}" Content="{Binding Path= Height, RelativeSource = {RelativeSource Self}}"/>

중괄호에 정의된 값들은 접두사를 제외한 첫번째 식별자가 마크업 확장식 클래스의 이름이다. 일반적으로 XAML에서는 클래스와 달리 접미사를 떼고 사용한다.

 

Object Element의 자식요소들

오브젝트 엘리먼트는 보통 세가지 형대틔 자식 엘리먼트를 가질수 있다

컨텐트 프로퍼티

대부분의 WPR 클래스들은 사용자 지정 어트리 뷰트를 사용해서 XML 엘리먼트 안쪽의 내용과 관계없이 프로퍼티를 설정할수 있도록 설계되었다.그 역할을 하는 것이 바로 content property이다.

컨텐트 프로퍼티는 실제로 content 키워드 외에 어떤 것도 필요로 하지 않는다. 주의 할  것은 ListBox, TabControl, ComboBox처럼 몇몇 컨트롤은

컨텐트 프로퍼티를 대신해서 아이템즈(items)프로퍼티를 사용한다.

ex.A 방식

<Button>OK</Button>

B 방식

<Button>

<Button.Content>

<Rectangle Height="40" Width="40" Fill="Black">

</Button.Content>

</Button>

C방식

<Button>

<Rectangle Height="40" WIdth="40" Fill="Black">

</Button>

컬렉션아이템

XAML은 인덱싱을 지원하는 list와 Dictionary 등 두가지 컬렉션 형태의 프로퍼티를 갖고 있다.

리스트 - ArrayList처럼 System.Collections.IList를 구현한 컬렉션이다.

ex.

<ListBox >

<ListBox.Items>

<ListBoxItem Content="1"/>

<ListBoxItem Content="2"/>

</ListBox.Items>

</ListBox>

 

Items는 리스트박스의 컨텐트 프로퍼티이기때문에 다음처럼 줄일수 있다.

<ListBox >

<ListBoxItem Content="1"/>

<ListBoxItem Content="2"/>

</ListBox>

 

딕셔너리 - 다음에 다시

 

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2009. 1. 28. 14:56

ListBox는 여러개의 객체를 보여주는 Element이다.

그리고 ListBox에 특정 DataTemplate을 ItemTemplate으로 지정하면 원하는 형태로

데이타를 보여줄수 있다.

여기에 객체 리스트를 ItemsSource로 주면 바인딩을 할수 있다.

객체리스르의 변화를 ListBox에 반영하고 싶다면

객체리스트는 INotifyCollectionChanged인터페이스가 구현되어 있는

ObservableCollection<T>을 사용하면 된다.

이때 바인딩의 의미란 Collection 의 변화에 대해서 ListBox에 반영한다는 의미이다.

즉, Collection의 아이템이 추가 되었는지 혹은 삭제 되었는지를 반영하게 되는

Collection과 ListBox와의 바인딩이다.

그러므로 Collection의 한 객체의 내용이 변한 것은 Collection 입장에서는 변화가 없는 것이므로

ListBox의 한 객체에 대한 변경사항이 UI이 반영되지 않는다.

Collection의 한 객체변경사항이 ListBox에 반영되게 하려면

CollectionChanged Event 핸들러에서 혹은 Collection의 한 객체내용을 변경한 다음에

ListBox_Name.Items.Refresh()를 호출하게 되면 개별객체의 변경사항이 UI이 반영되게 된다.

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 12. 4. 11:43
  • 같은 XAML의 특정 Element의 값을 바인딩시킬때

    사용하고자하는 element 이름 - do

    사용하는 element 이름 - hyun

    <TextBlock x:Name = "hyun" Text= "{Binding Path=do의 프로퍼티이름, ElementName = do}" />

 

 

  • 비하인드 코드의 멤버변수 (혹은 프로퍼티)를 바인딩시킬때

    비하인드에서 다음과 같이 element이름을 정해준다

    C#

    Name ="behindDo";

    XAML

    <TextBlock x:Name = "hyun" Text= "{Binding Path=behindDo의 프로퍼티이름, ElementName = behindDo}" />

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 11. 26. 17:21

 string path = System.Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData) + "\\xxxx\\yyyyy";
           
            if (!Directory.Exists(path))
            {
                Directory.CreateDirectory(path);
            }

            string guestName = "Guest.dat";
            string localDB = "LocalPhoneBook.dat";
            string srcPath = "";

            if (!File.Exists(path + "\\" + guestName))
            {
                srcPath = "./" + guestName;
                File.Copy(srcPath, path + "\\" + guestName);
            }

            if (!File.Exists(path + "\\" + localDB))
            {
                srcPath = "./" + localDB;

                File.Copy(srcPath, path + "\\" + localDB);
            }

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 11. 26. 17:14

msdn에는 += 를 이용한 FilterEventHandler 등록이 가능한 것으로 나와 있으나 ex. listingDataView.Filter += new FilterEventHandler(ShowOnlyBargainsFilter);

문법적인 오류가 나서 확인하지 못했음

그래서 저같은 경우 object를 받아서 처리하는 필터함수를 만들어서 Filter Property에 저장하는 식으로 사용했습니다.

 

 

함수 등록

CollectionView leftView = (CollectionView)CollectionViewSource.GetDefaultView(PcPhoneBookLsv.ItemsSource);
leftView.Filter = new Predicate<object>(PhoneBookSearchFilter);

 

함수 등록 해지

CollectionView leftView = (CollectionView)CollectionViewSource.GetDefaultView(PcPhoneBookLsv.ItemsSource);           
                leftView.Filter = null;

 

등록된 함수

private bool PhoneBookSearchFilter(object e)
        {
            PhonebookItem pbItem = e as PhonebookItem;
            string searchStr = ui_txtSearch.Text;
            if (searchStr == "")//검색어가 없을때
            {
                //e.Accepted = true;               
                return true;
            }
            //PhonebookItem pbItem = e.Item as PhonebookItem;
            if (pbItem != null)
            {
                if ((pbItem.FirstName.Contains(searchStr)) || (pbItem.LastName.Contains(searchStr)) || ((pbItem.LastName + pbItem.FirstName).Contains(searchStr)) ||
                    (pbItem.MobileNum.Contains(searchStr)) || (pbItem.HomeNum.Contains(searchStr)))
                {//지정 필드가 검색어를 포함할 경우
                    //e.Accepted = true;
                    return true;
                }
                else
                {//포함하지 않을 경우
                    //e.Accepted = false;
                    return false;
                }
            }
            else
                return false;
        }

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 11. 17. 05:31

FrameworkElement..::.Unloaded 이벤트 를 등록해서 사용한다

 

로드된 요소의 요소 트리에서 요소를 제거할 때 발생합니다.

 

직접 라우트된 이벤트는 경로를 따르지 않으며 발생한 요소 내에서만 처리됩니다. 직접 라우트된 이벤트는 다른 라우트된 이벤트 동작을 지원합니다. 즉, 액세스 가능한 처리기 컬렉션을 지원하며 스타일에서

EventTrigger로 사용할 수 있습니다.

Loaded 및 Unloaded는 사용자가 시작한 시스템 테마 변경 작업의 결과로 컨트롤에서 발생할 수 있습니다. 테마를 변경하면 컨트롤 템플릿 및 포함된 시각적 트리가 무효화되므로, 전체 컨트롤을 언로드 및 다시 로드할 수 없게 됩니다. 그러므로 페이지 탐색을 통해 페이지를 벗어나 탐색할 때만 Unloaded가 발생하는 것은 아닙니다.

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 11. 17. 01:27

Grid에서의 Star 크기 조정. 만일 열이나 행의 너비나 높이를 스타로 지정하면 이는 Grid 패널이 고정된 너비나 자동 조정된 너비를 가지는 아이템의 나머지 공간을 채우도록 하는 것이다. 만일 여러

아이템에 스타를 지정하면 각 요소들이 공간을 나누어 사용하게 된다.

만일 다음과 같은 코드라면

ex

<Grid.RowDefinitions>

<RowDefinition Height-"Auto" />

<RowDefinition Height="@*" />

<RowDefinition Height="1*" />

</Grid.RowDefinitions>

첫번째 행은 자동조정되며, 두번째 행은 첫번째 행보다 두배로 높이를 가지게 된다. 그리드 전체가 350이고 첫번째가 50이라면 두번째는 200, 마지막은 100의 높이를 가지게 되는 것이다.

by 무위자연 2008. 11. 4. 09:39

private void PhoneItemLbx_MouseDoubleClick(object sender, MouseButtonEventArgs e)
        {
           DependencyObject dep = (DependencyObject)e.OriginalSource;   //마우스 이벤트가 발생한 곳의 원본소스를 이용한다.
           while ((dep != null) && !(dep is ListViewItem))
           {
               dep = VisualTreeHelper.GetParent(dep);// 클릭한 대상중에 ListItem이 있으면 순회문 중단
           }
          
            if(dep == null)// 리스트뷰의 리스트 아이엠 외의 곳을 더블클릭한 것
                MessageBox.Show("you clicked empty space");
            else
            {// 리스트뷰의 특정 아이템을 더블 클릭한 것
                PhonebookItem item = (PhonebookItem)PhoneItemLbx.ItemContainerGenerator.ItemFromContainer(dep);
            }           

        }

 

 

RoutedEventArgs..::.OriginalSource 속성

부모 클래스에서 소스를 조정하기 전에 순수 적중 테스트에 의해 결정되는 원본 보고 소스를 가져옵니다.

VisualTreeHelper 클래스

시각적 트리의 노드와 관련된 일반적인 작업을 수행하는 유틸리티 메서드를 제공합니다.

GetParent > 표시 개체의 부모를 나타내는 DependencyObject 값을 반환합니다.

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 10. 30. 10:49

- UI 요소에 외형적인 특성을 추가하기 위한 특별한 목정의 사용자 정의 요소이다. 하나의 장식 객체는 자신을 사용하는 요소와 동일한 위치에 나타나지만

Z순서상 가장 위에 나타날 것이다. 즉, 창에서 모든 비장식 요소보도 위에 타나난다. 장식 객체들은 보통 대화명 객체 수정 시나리오에서 선택된 객체의 외곽선을 표시하거나 제어하기 위해 사용된다.

WPF는 Z 순서위에 특별한 AdornerLayer 요소를 생성하기때문에 장식 객체들은 최상위에 나타날수 있다.

 

AdornerLayer 객체는 여러개의 증복된 요소를 폼할수 있기때문에 패널의 일종이라고 생각할수 있다. 그러나 AornerLayer는 FrameworkElement 클래스를 직접 상속하고 있으며 두가지 이유에서 패널로 취급하지 않는다.

  • 패널은 모든 UI요소를 포함할수 있는 반면 이 클래스는 Adorner 클래스 를 상속한 요소만 포함할수 있다.
  • AdornerLayer 클래스는 자신이 장식하는 요소의 위치에 따라 장식 레이어 상에 위치하게 되며, 자신 만의 독자적인 레이아수 로직은 가지고 있지 않다. 이는 장식 객체들은 일반적인 방식의 레이아웃에는 관여 하지 않는 것을 의미한다.

 

Adorner  기반 클래스에서 파생되는 고용 클래스는 존재 하지 않으므로 어쩔수 없이 이 를 상속하여 직접 클래스를 구현해야 한다. 또한, Adorner 클래스는 속성을 통해 그 외형을 정의할수 없기때문에 XAML을 쓸 수 없다.

ex 장식 비주얼 레이어 사용

class BoxingAdorner : Adorner

{

public BoxingAdorner(UIElement adornedElement) : base (adornedElement) {}

 

protected override void OnRender(DrawingContext drawingContext)

{

drawingContext.DrawRectangle(null, new Pen(Brushes.Blue, 2), new Rect(0 , 0, 100, 40));

}

}
ex 장식 객체를 사용하는 예제

//xaml

<Window ..>

<Grid>

<TextBlock x:NAme="targetEelment" Margin="40,40,0,0" Text="안녕하세요"/>

</Grid>

</Window>

//c#

partial class Window1 :Window

{

public Window1()

{

InitializeComponent();

this.Laoded += new RoutedEventHandler(Windwo1_Loaded);

}

void Winodow1_Loaded(object sender, RoutedEventArgs e)

{

AdornerLayer a1 = AdornerLayer.GetAdornerLayer(targetElement);

BoxingAdorner myAdorner = new BoxingAdorner(targetElement);

a1.Add(myAdorner);

}

 

}

 

 

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 10. 2. 16:27

원본

데이터 바인딩의 정의

데이터 바인딩은 응용프로그램 UI와 비지니스 논리를 서로 연결하는 프로세스이다. 바인딩 설정이 올바르고 데이터가 적절한 알림을 제공하는 경우에는 데이터의 값이 변경될때

데이터에 바인딩된 요소에 변경 내용이 자동으로 반영된다.

 

일반적인 용도는 서버 또는 로컬 구성 데이터를 폼이나 기타 UI 콘트롤에 배치하는 것.

 

기본 바인딩 개념

바인딩하려는 요소 및 데이터 소스의 특성에 관계 없이 각  바인딩은 항상 다름 그림에 나타나는 모델을 따릅니다.

<이미지 출처 : msdn https://msdn.microsoft.com/en-us/library/hh848246.aspx



  • 데이터 바인딩은 기본적으로 바인딩 대상과 바인딩 소스 사이의 다리 역할을 한다.
  • 대상 속성은 종속성 속성이어야 한다. UIElement 속성 대부분은 종속성 속성이며 읽기 전용 속성을 제외한 대부분의 종속성 속성은 기본적으로 데이터 바인딩을 지원한다.
  • DependencyObject 형식만 종속성 속성을 정의할수 있다.

 

소스 업데이트를 트리거하는 항목

TwoWay, OneWayToSource인 바인딩은 대상 속성의 변경 내용을 수신하고 해당 변경 내용을 다시 소스로 전파합니다. 이것을 소스 업데이트라고 한다.

텍스트를 편집하고 있을때나 텍스트 편집을 마치고 마우스를 TextBox 외부로 움직였을때 소스 값이 업데이트 될까요?  소스 업데이트는 바인딩의 UpdateSourceTrigger속성에 따라 결정된다.

UpdateSourceTrugger 값이 PropertyChanged이면 대상 속성이 변경되는 즉시 업데이트가 일어나고 LostFocus 이면 대상 속성이 포커스를 잃었을때에만 해당 값이 업데이트 된다.

 

바인딩 만들기

바인딩 소스 지정 - 여러 속성을 같은 소스에 바인딩할때 부모요소에 DataContext속성을 사용하는 방법이 유용하다. 개별적인 경우 DataContext 대신 Source속성을 이용할수도 있다.

값에 대한 경로 지정 - 바인딩 소스가 개체일때는 Path속성을 사용하여 바인딩에 사용할 값을 지정합니다.

 

데이터 변환

[ValueConversion(typeof(Color), typeof(SolidColorBrush))]
public class ColorBrushConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        Color color = (Color)value;
        return new SolidColorBrush(color);
    }

    public object ConvertBack(object value, Type targetType, object parameter, System.Globalization.CultureInfo culture)
    {
        return null;
    }
}

ms752347.DataBindingConverterColorExample(ko-kr,VS.90).png

 

바인딩하는 형식에 있는 형식  변환기때문에 기본변환을 사용할수 있다.  형식변환기를 직접 구현하는 경우는

  • 데이터를 문화권에 따라 드라게 표시해야 하는 경우
  • 사용되는 데이터를 반드시 속성의 텍스트 값으로 변경할 필요는 없지만 이미지의 소스 또는 표시 텍스트의 색이나 스타일과 같은 다른 값으로 변경해야 하는 경우
  • 둘 이상의 콘트롤 또는 콘트롤의 여러 속성을 같은 데이터에 바인딩하는 경우
  • MultiBinding 의 경우 사용자 지정 IMultiValueConverter를 사용하여 바인딩의 값에서 최종 값을 생성한다.

 

 

컬렉션에 바인딩.

바인딩 소스 개체는 속성에서 데이터를 포함하는 단일 개체 또는 함께 그룹화되는 경우가 많은 다형성 개체의 데이터 컬렉션으로 취급될수 있다.

컬렉션 구현방법

IEnumberable 인터페이스를 구현하는 모든 컬렉션을 열거할수 있다. 그러나 컬렉션에 삽입이나 삭제를 수행할때 UI가 자동으로 업데이트되도록 동적 바인딩을 설정하려면

컬렉션에서 INotifyCollectionChanged 인터페이스를 구현해야 한다. 이 인터페이스는 내부컬렉션이 변경될때마다 발생해야 하는 이벤트를 노출한다.

WPF에서는 INotifyCollectionChanged 인터페이스를 노출하는 데이터 컬렉션에 대한 기본 제공 구현인 ObservableCollection(T) 클래스를 제공한다.

컬렉션뷰의 정의

컬렉셔뷰는 기본 소스 컬렉션  자체를 조작할 필요없이 필터, 정렬, 그룹화 쿼리를 기반으로 소스 콜력션을 탐색하고 표시하는 사용할수 있는 바인딩 소스 콜렉션의 최상위 계층으로 간주할수 있다.INOtifyCOllectionChanged 페이스가 소스 콜렉션에서 구현될 경우 CollectionChanged이벤트에서 발생되는 변경내용은 뷰로 전파됩니다.

뷰는 기본 소스 컬렉션을 변경하지 않으므로 각 소스 컬렉션에 여러개의 뷰를 연결하여 사용할수 있다.

뷰 사용법 중에 하나는 뷰 개체를 직접 인스턴스화한 다음 이를 바인딩 소 스로 사용하는 방법이다.

 

정렬

ex.

private void AddSorting(object sender, RoutedEventArgs args)
{  
    listingDataView.SortDescriptions.Add(
        new SortDescription("Category", ListSortDirection.Ascending));
    listingDataView.SortDescriptions.Add(
        new SortDescription("StartDate", ListSortDirection.Ascending));
}

 

필터

ex.

listingDataView.Filter += new FilterEventHandler(ShowOnlyBargainsFilter);

 

private void ShowOnlyBargainsFilter(object sender, FilterEventArgs e)
{
    AuctionItem product = e.Item as AuctionItem;
    if (product != null)
    {
        // Filter out products with price 25 or above
        if (product.CurrentPrice < 25)
        {
            e.Accepted = true;
        }
        else
        {
            e.Accepted = false;
        }
    }
}

 

그룹화 - 뷰에서 그룹화 기능을 지원하므로 사용자는 컬렉션 뷰의 컬렉션을 놀리 그룹으로 분할할수 있다. 사용자가 그룹 목록을 제공할 경우 그룹은 명시적이며 그룹이 데이터에 따라 동적으로 생성될 경우 그룹은 암시적이다.

ex.// This groups the items in the view by the property "Category"
PropertyGroupDescription groupDescription = new PropertyGroupDescription();
groupDescription.PropertyName = "Category";
listingDataView.GroupDescriptions.Add(groupDescription);

 

현재 레코드 포인터

컬렉션 뷰에서 개체를 탐색할수 있다. 탐색할때 레코드 포인터를 이동하여 컬렉션의 특정 위치에 있는 개체를 검색할수 있다.

현재 레코드 포인터 이동은 컬렉션에 적용되는 정렬 똔느 필터링과  몇 가지 상호 작용을 한다. 정렬이 적용되는 경우에는 선택한 마지막 레코드에 현재 레코드 포인터가 유지되지만

해당 레코드 주위에서 컬력센 뷰가 재구성됩니다. 

 

마스터-세부 바인딩 시나리오

 

데이터 템플릿

ex.

<DataTemplate DataType="{x:Type src:AuctionItem}">
    <Border BorderThickness="1" BorderBrush="Gray"
            Padding="7" Name="border" Margin="3" Width="500">
        <Grid>
          <Grid.RowDefinitions>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
            <RowDefinition/>
          </Grid.RowDefinitions>
          <Grid.ColumnDefinitions>
            <ColumnDefinition Width="20"/>
            <ColumnDefinition Width="86"/>
            <ColumnDefinition Width="*"/>
          </Grid.ColumnDefinitions>

            <Polygon Grid.Row="0" Grid.Column="0" Grid.RowSpan="4"
                     Fill="Yellow" Stroke="Black" StrokeThickness="1"
                     StrokeLineJoin="Round" Width="20" Height="20"
                     Stretch="Fill"
                     Points="9,2 11,7 17,7 12,10 14,15 9,12 4,15 6,10 1,7 7,7"
                     Visibility="Hidden" Name="star"/>

            <TextBlock Grid.Row="0" Grid.Column="1" Margin="0,0,8,0"
                       Name="descriptionTitle"
                       Style="{StaticResource smallTitleStyle}">Description:</TextBlock>
            <TextBlock Name="DescriptionDTDataType" Grid.Row="0" Grid.Column="2"
                Text="{Binding Path=Description}"
                Style="{StaticResource textStyleTextBlock}"/>

            <TextBlock Grid.Row="1" Grid.Column="1" Margin="0,0,8,0"
                       Name="currentPriceTitle"
                       Style="{StaticResource smallTitleStyle}">Current Price:</TextBlock>
            <StackPanel Grid.Row="1" Grid.Column="2" Orientation="Horizontal">
                <TextBlock Text="$" Style="{StaticResource textStyleTextBlock}"/>
                <TextBlock Name="CurrentPriceDTDataType"
                    Text="{Binding Path=CurrentPrice}"
                    Style="{StaticResource textStyleTextBlock}"/>
            </StackPanel>
        </Grid>
    </Border>
    <DataTemplate.Triggers>
        <DataTrigger Binding="{Binding Path=SpecialFeatures}">
            <DataTrigger.Value>
                <src:SpecialFeatures>Color</src:SpecialFeatures>
            </DataTrigger.Value>
          <DataTrigger.Setters>
            <Setter Property="BorderBrush" Value="DodgerBlue" TargetName="border" />
            <Setter Property="Foreground" Value="Navy" TargetName="descriptionTitle" />
            <Setter Property="Foreground" Value="Navy" TargetName="currentPriceTitle" />
            <Setter Property="BorderThickness" Value="3" TargetName="border" />
            <Setter Property="Padding" Value="5" TargetName="border" />
          </DataTrigger.Setters>
        </DataTrigger>
        <DataTrigger Binding="{Binding Path=SpecialFeatures}">
            <DataTrigger.Value>
                <src:SpecialFeatures>Highlight</src:SpecialFeatures>
            </DataTrigger.Value>
            <Setter Property="BorderBrush" Value="Orange" TargetName="border" />
            <Setter Property="Foreground" Value="Navy" TargetName="descriptionTitle" />
            <Setter Property="Foreground" Value="Navy" TargetName="currentPriceTitle" />
            <Setter Property="Visibility" Value="Visible" TargetName="star" />
            <Setter Property="BorderThickness" Value="3" TargetName="border" />
            <Setter Property="Padding" Value="5" TargetName="border" />
        </DataTrigger>
    </DataTemplate.Triggers>
</DataTemplate>

데이터 템플릿을 사용하면 데이터를 컨트롤에 넣을수 있을뿐 아니라 데이터를 시각적으로 뛰어나게 표현할수 있다.

 

데이터 유효성 검사

사용자 입력을 받는 대부분의 응용프로그램은 사용자가 올바른 정보를 입력했는지 확인하기 위한 유효성 검사 논리가 필요하다 유효성 검사는 형식, 범위, 서식 또는 기타 응용프로그램별

요규사항을 기반으로 할수 있다.

ex 유효성 검사 규칙을 바인딩과 연결

<TextBox Name="StartPriceEntryForm" Grid.Row="2" Grid.Column="1"
    Style="{StaticResource textStyleTextBox}" Margin="8,5,0,5">
  <TextBox.Text>
    <Binding Path="StartPrice" UpdateSourceTrigger="PropertyChanged">
      <Binding.ValidationRules>
        <ExceptionValidationRule />
      </Binding.ValidationRules>
    </Binding>
  </TextBox.Text>
</TextBox>

WPF 데이터 바인딩 모델을 사용하면 ValidationRules를 Binding 객체와 연결할수 있다.

 

시각적 피드백 제공

ex.

<ControlTemplate x:Key="validationTemplate">
  <DockPanel>
    <TextBlock Foreground="Red" FontSize="20">!</TextBlock>
    <AdornedElementPlaceholder/>
  </DockPanel>
</ControlTemplate>

 

유효성 검사 프로세스

ms752347.DataBindingValidation(ko-kr,VS.90).png

  1.  대상 속성에서 소스 속성으로 값이 전송중인 경우 데이터 바인딩 엔진은 먼저 바인딩된 요소의 Validation.Errors 연결된 속성에 추가되었을 수 있는 ValidationError 를 모두 제거.
  2. 그런 다음 해당 Binding 에 대해 정의된 사용자 지정 ValidationRule 이 있는지 확인한 다음 있으면 해당 규칙 중 하나가 오류를 만나거나 모두 통과할때까지 각 ValidationRule에 대해 Validation 메소드를 호출합니다
  3. 통과되지 않은 사용자 지정 규칙이 있으면 바인딩 엔진은 ValidationError 개체를 만들어 바인딩된 요소의 Validation.Error 컬렉션에 추가합니다. Validation.Errors가 비어 있지 않으면 요소의 Validation.HasError연결된 속성은 ture로 설정됩니다. 또 Binding의 NotifyOnCalidationError속성이 true로 설정되어 있는 경우 바인딩 엔진은 요소에 대해 Validation.Error 연결된 이벤트를 발생시킨다
  4. 모든 규칙이 통과되는 경우 바인딩 엔진은 변환기를 호출합니다
  5. 변환기가 통과되면 바인딩 엔진은 소스 속성의 setter를 호출한다
  6. 바인딩에 연결된 ExceptionValidationRule이 있고 5 단계에서 예외가 throw되는 경우 바인딩 엔진은 UpdateSourceExceptionFilter가 있는지 확인합니다.

    UpdateSourceExceptionFilter 콜백을 사용하여 예외 처리를 위한 사용자 지정 처리기를 제공할수 있다. Binding에서 UpdateSourceExceptionFilter가 지정되지 않은 경우 바인딩 엔진은 예외가 있는 ValidationError를 만들어 바인딩된 요소의 Validation.Errors컬렉션에 추가합니다.

 

이 글은 스프링노트에서 작성되었습니다.

by 무위자연 2008. 9. 24. 14:05
| 1 2 3 4 |