퇴근5분전

데이타템플릿
 ListBox에 ToString() 말고, 임의의 모습으로 나타내고자 할때 사용할수 있음.

사용자 삽입 이미지
<DataTemplate으로 적용된 화면>


Window.xaml
<Window x:Class="OneTimeDataBinding.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"       
    xmlns:myClass="clr-namespace:OneTimeDataBinding"
    Title="Window1" Height="236" Width="300" Loaded="Window_Loaded">
    <Window.Resources>
        <myClass:Code x:Key="cd" Name="_ResourceName" ></myClass:Code>

        <DataTemplate x:Key="dt" DataType="{x:Type myClass:Code}">
          <StackPanel Orientation="Horizontal">
             <TextBlock Text="{Binding Path=Name}" Foreground="Blue"></TextBlock>
             <TextBlock Text=":"></TextBlock>
             <TextBlock Text="{Binding Path=Age}" Foreground="Chartreuse"></TextBlock>               
            </StackPanel>
               
        </DataTemplate>    

    </Window.Resources>
    <Grid Height="289" x:Name="Grid1" DataContext="{StaticResource cd}">
        <Grid.RowDefinitions>
            <RowDefinition Height="65*" />
            <RowDefinition Height="224*" />
        </Grid.RowDefinitions>
        <TextBox Margin="12,12,73,10" Name="textBox1" Text="{Binding Path=Name}" />
        <Button HorizontalAlignment="Right" Margin="0,12,12,10" Name="button1" Width="55" Click="button1_Click">Button</Button>
        <Grid Name="Grid2" Margin="0,12,0,100" Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="132*" />
                <ColumnDefinition Width="146*" />               
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="89.473*" />
                <RowDefinition Height="23.527*" />
            </Grid.RowDefinitions>
            <TextBlock Text="{Binding Path=Name}" Margin="12,0,12,6" Grid.Row="1" Height="17.527" VerticalAlignment="Bottom"></TextBlock>
            <TextBlock Text="{Binding Path=Age}" Margin="12,0,26,10" Grid.Row="1" Grid.Column="1" Height="13.527" VerticalAlignment="Bottom"></TextBlock>
            <ListBox Margin="12,6,0,6" Name="listBox1" ItemsSource="{Binding}" Grid.ColumnSpan="2"
                 HorizontalAlignment="Left" Width="260" SelectionChanged="listBox1_SelectionChanged"
                  ItemTemplate="{StaticResource dt}" />
        </Grid>
    </Grid>
</Window>

Window.xaml.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using System.ComponentModel;

namespace OneTimeDataBinding
{
    /// <summary>
    /// Window1.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class Window1 : Window
    {
        Code cd = new Code();

        public Window1()
        {
            InitializeComponent();
            cd.Name = "초기 코드값";
            Grid1.DataContext = cd;
        }
      

        private void button1_Click(object sender, RoutedEventArgs e)
        {
           cd.Name = "변경 값";          
           //MessageBox.Show(cd.Name);
        }

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            CodeList cd = new CodeList();
            cd.Add(new Code() { Name = "Code1", Age=1});
            cd.Add(new Code() { Name = "Code2", Age=2 });
            cd.Add(new Code() { Name = "Code3", Age=3 });

            listBox1.DataContext = cd;
        }

        private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Grid2.DataContext = e.AddedItems; 
        }
    }

    ///// <summary>
    ///// 단일 바인딩 모델에서 사용한 클래스.
    ///// </summary>
    //public class Code
    //{
    //    string name = string.Empty;
    //    public string Name { get; set; }
    //}

    /// <summary>
    /// 코드 리스트
    /// </summary>
    public class CodeList : List<Code>
    {

    }


    /// <summary>
    ///
    /// 단방향 모델에서 사용한 클래스.
    /// </summary>
    public class Code : INotifyPropertyChanged
    {
        string name = string.Empty;

        public string Name { get { return name; } set { name = value; Update("Name"); } }

        int age = 0;

        public int Age { get { return age; } set { age = value; Update("Age"); } }


        #region INotifyPropertyChanged 멤버

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        public void Update(string PropertyName)
        {
            if( PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
        }

        public override string ToString()
        {
            return name;
        }
    }

}

특정 객체에 저장된 데이타가 출력되는 화면을 정의하여 템플릿화 할수 있는데
이를 데이타 템플릿이라 한다.

ObservableCollection<T> : 책에 오타 있으므로 철자 주의!

위 소스에서 이전, 다음 버튼을 추가후 각각 버튼 처리를 한다.

// 이전
       private void button2_Click(object sender, RoutedEventArgs e)
        {
            ICollectionView view = CollectionViewSource.GetDefaultView(listBox1.DataContext);
            view.MoveCurrentToPrevious();
            if (view.IsCurrentBeforeFirst)  view.MoveCurrentToFirst();
            //Grid2.DataContext = view.CurrentItem as Code;
            listBox1.SelectedItem = view.CurrentItem;
        }
//다음
        private void button3_Click(object sender, RoutedEventArgs e)
        {
            ICollectionView view = CollectionViewSource.GetDefaultView(listBox1.DataContext);
            view.MoveCurrentToNext();
            if (view.IsCurrentAfterLast)  view.MoveCurrentToLast();
            //Grid2.DataContext = view.CurrentItem as Code;
            listBox1.SelectedItem = view.CurrentItem;
        }

이때 새로운 데이타 추가시~~ CodeList 가 변경 되는데 이때 컨트롤에 적용시키는 기능이 포함되어 있지 않다.

INotifyPropertyChanged 인터페이스가 List<T>에는 적용되어 있지 않아 갱신되지 않으므로
WPF에서는 이를 적용한 ObservableCollection<T> 제너릭컬렉션에 데이타를 저장하면 자동으로 갱신된다.

테스트 해보니 일반 List<T>를 사용하여 추가기능을 구현했을때는
추가후 ListBox에 추가된 Item은 보이지 않았음.

ObservableCollection<T>를 사용하여 구현하니 추가시 바로 갱신되는것을 확인하였음.

    public class oCodeList : ObservableCollection<Code>
    {    
    }

public class Window1 : Window
{
       ...

        private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            oCodeList cd = new oCodeList();
            // CodeList cd = new CodeList();           
            cd.Add(new Code() { Name = "Code1", Age=1});
            cd.Add(new Code() { Name = "Code2", Age=2 });
            cd.Add(new Code() { Name = "Code3", Age=3 });

            listBox1.DataContext = cd;
        }

       /// 추가 기능
       private void button4_Click(object sender, RoutedEventArgs e)
        {
            oCodeList ls = listBox1.DataContext as oCodeList;
            //CodeList ls = listBox1.DataContext as CodeList;
            if (ls != null)
                ls.Add(new Code() { Name="add1", Age=ls.Count+1 });
        }
}

컨트롤 데이타 바인딩
 임의의 WPF 컨트롤에 설정된 데이타를 다른 컨트롤에 바인딩 할수도 있다.
이때 속성대 속성의 매칭을 통해 데이타의 이동이 발생한다.

간단히 바인딩 표현식이 바뀐다

<바인딩컨트롤
      Background="{Binding ElementName=대상컨트롤이름, Path=대상컨트롤속성이름}" ...
 />

책페이지 321부터 간략히 설명되있음...


me : 바인딩에 대해 2회로 나누어 확인하였음.
DataTemplate를 가지고 표시되는 형태를 마음대로 바꿀수 있다는 점이 역시 흥미로웠음.
다른부분은 .Net 2.0에서 코딩량이 좀 되지만 나름 구현이 가능했던 것들이라...
WPF에서의 바인딩 구현방법이 좀더 편하다는 생각이 들기도 했지만... 데이타 타입별로 Class화 해야된다면 파일또한 많아 지겠구나 싶었음. 필요하다면 지금까지 해왔던 방법대로 DataTable을 바인딩 걸어서 써보고 싶음.




- 출처 : .Net 3.5 차세대 개발 프로그래밍 -  책에서 일부 정리 함. ( 저작권 문제시 삭제 할 것임. )
          자세한 내용은 책을 통해 확인하시길...

'# 3) .Net ( Vs 2008 ) > WPF' 카테고리의 다른 글

툴을 제작 해서 프로젝트를... 진행하다!  (0) 2010.02.26
WPF 3D  (0) 2009.12.29
데이타바인딩(1)  (0) 2009.12.28
이벤트 종류 & 명령 & 트리거  (0) 2009.12.28
컨트롤  (0) 2009.12.28

데이타 바인딩 모델
  1. 단일         : 읽기전용 바인딩 모델
  2. 단방향      : 읽기전용 바인딩 모델 & 저장소데이타 변경시 자동 변경
  3. 양방향      : 읽기/쓰기 바인딩 모델

- 단일
  데이타를 값 대입해주는 형태로 사용함.( 기존 Form작업시 많이 사용했음. )
 컨트롤.프로퍼티 = 저장소.프로퍼티;

- 단방향
  객체의 상태변화를 이용해서 변경시 자동으로 바인딩된 컨트롤에 반영되도록 해주는 모델
  -- 객체 상태 변화
   객체의 상태변화시 System.ComponentModel.INotifyPropertyChanged 를 이용하여 제어가 가능하다.
 
    /// <summary>
    /// 단방향 모델에서 사용한 클래스.
    /// </summary>
    public class Code : INotifyPropertyChanged
    {
        string name = string.Empty;
        public string Name { get { return name; } set { name = value; Update("Name"); } }

        #region INotifyPropertyChanged 멤버
        public event PropertyChangedEventHandler PropertyChanged;
        #endregion
        public void Update(string PropertyName)
        {
            if( PropertyChanged != null)
              PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));
        }
    }
 
   이렇게 인터페이스를 구현하고 윈도우폼 상에서 이벤트를 정의 하여 객체 변화 시
  데이타를 갱신해주는 형태로 구현이 된다.

책에는 양방향 언급이 초반에 살짝 있고 사라졌다...
대신 바인딘 표현식 이란것으로 대체 한듯한데...

바인딩 표현식
           Code cd = new Code();
           cd.Name = "초기 코드값";
           textBox1.DataContext = cd;  // 데이타 원본 할당
데이타를 컨트롤에 바인딩 하고
<TextBox  Name="textBox1" VerticalAlignment="Top" Text="{Binding Path=Name}" />
컨트롤 프로퍼티에 바인딩되는 데이타객체의 프로퍼티를 지정하여 결정한다.



바인딩 방향에 대한 문제는 저장소 객체 -> 데이타표출컨트롤 쪽에 해당하는 문제인듯 함.
이유:
 테스트 해본결과
    1. 저장소객체와 컨트롤을 바인딩 : <... Text="{Binding Path=Name}" />
    2. 저장소객체의 프로퍼티를 이용한 데이타 변경 :  데이타 표출컨트롤 반영 안됨.
    3. 데이타표출컨트롤에서 값 변경 : 저장소객체 데이타변경되있음.

private void UpdateBtn_Click(object sender, RoutedEventArgs e)
{
      cd.Name = "변경 값";                  
}

일때

    /// <summary>
    /// 단방향 모델에서 사용한 클래스.
    /// </summary>
    public class Code : INotifyPropertyChanged
    {
        string name = string.Empty;

        public string Name { get { return name; } set { name = value; Update("Name"); } }

        #region INotifyPropertyChanged 멤버

        public event PropertyChangedEventHandler PropertyChanged;

        #endregion

        public void Update(string PropertyName)
        {
            if( PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(PropertyName));       // -----①
        }
    }

따로 Code객체에 PropertyChanged 에 이벤트핸들러를 추가하지 않고 있으나

① 이 주석여부에 따라~!!!  표출컨트롤에 데이타 갱신이 일어나는것으로 보아
 바인딩 될때 내부적으로 PropertyChanged 이벤트에 핸들러를 추가하는듯 함.

의존 속성 ( Dependency Property )
 
Window.xaml
 <Grid Height="48" x:Name="Grid1">
        <TextBox Height="23" Margin="12,12,73,0" Name="textBox1" VerticalAlignment="Top" Text="{Binding Path=Name}" />
        <Button Height="23" HorizontalAlignment="Right" Margin="0,12,12,0" Name="button1" VerticalAlignment="Top" Width="55" Click="button1_Click">Button</Button>
    </Grid>

Window.xaml.cs
        Code cd = new Code();
        public Window1()
        {
            InitializeComponent();
            cd.Name = "초기 코드값";
            Grid1.DataContext = cd;
        }
 
위와 같이 TexBox에 바인딩 표현식이 존재하나 실제 바인딩 원본은 Grid1.DataContext 에 바인딩 되어있을시  그리드에 하위 요소인 TextBox에서는 자신에게 바인딩된 원본이 없으므로 상위 객체에서 바인딩원본을 찾게 된다. 이때 Text 가 곧 의존 속성이 된다. ( 이해한대로 썼음... )


선언적 데이타 원본

<Window.Resources>
   <Code x:Key="cd" xmlns="clr-namespace:OneTimeDataBinding" Name="_ResourceName" ></Code>
</Window.Resources>
   <Grid Height="48" x:Name="Grid1" DataContext="{StaticResource cd}">
        <TextBox Height="23" Margin="12,12,73,0" Name="textBox1" VerticalAlignment="Top" Text="{Binding Path=Name}" />
        <Button Height="23" HorizontalAlignment="Right" Margin="0,12,12,0" Name="button1" VerticalAlignment="Top" Width="55" Click="button1_Click">Button</Button>
    </Grid>

이런식으로 되있다.

<Code> 는 컴파일시 Code 객체로 변환되고 그리드에 바인딩하고 TextBox는 의존속성에 의해 그리드에 원본데이타를 표시하게 됨.

선언적이란건 리소스에 데이타원본을 선언한다라는 의미인듯 하다.


다중 데이타 바인딩
 리스트 박스 같은 여러개의 객체를 바인딩 할때...

List를 이용하고 ToString을 재정의 하고, 의존속성을 이용하고 하니 간편하게 코딩이 가능하다눈...

책에 300페이지 ~ 307페이지 내용인데.

Window.xaml.cs
 private void Window_Loaded(object sender, RoutedEventArgs e)
        {
            CodeList cd = new CodeList();
            cd.Add(new Code() { Name = "Code1", Age=1});
            cd.Add(new Code() { Name = "Code2", Age=2 });
            cd.Add(new Code() { Name = "Code3", Age=3 });

            listBox1.DataContext = cd;
        }

        private void listBox1_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            Grid2.DataContext = e.AddedItems; 
        }

Window.xaml
 <Grid Name="Grid2" Margin="0,12,0,100" Grid.Row="1">
            <Grid.ColumnDefinitions>
                <ColumnDefinition Width="132*" />
                <ColumnDefinition Width="146*" />               
            </Grid.ColumnDefinitions>
            <Grid.RowDefinitions>
                <RowDefinition Height="89.473*" />
                <RowDefinition Height="23.527*" />
            </Grid.RowDefinitions>
            <TextBlock Text="{Binding Path=Name}" Margin="12,0,12,6" Grid.Row="1" Height="17.527" VerticalAlignment="Bottom"></TextBlock>
            <TextBlock Text="{Binding Path=Age}" Margin="12,0,26,10" Grid.Row="1" Grid.Column="1" Height="13.527" VerticalAlignment="Bottom"></TextBlock>
            <ListBox Margin="12,6,0,6" Name="listBox1" ItemsSource="{Binding}" Grid.ColumnSpan="2" HorizontalAlignment="Left" Width="260" SelectionChanged="listBox1_SelectionChanged" />
        </Grid>



꾀 길어졌는데 잘라볼까낭..

- 출처 : .Net 3.5 차세대 개발 프로그래밍 -  책에서 일부 정리 함. ( 저작권 문제시 삭제 할 것임. )
          자세한 내용은 책을 통해 확인하시길...

'# 3) .Net ( Vs 2008 ) > WPF' 카테고리의 다른 글

WPF 3D  (0) 2009.12.29
데이타바인딩(2)  (0) 2009.12.28
이벤트 종류 & 명령 & 트리거  (0) 2009.12.28
컨트롤  (0) 2009.12.28
스타일  (0) 2009.12.26

이벤트의 종류에는

 1. 직접 이벤트
 2. 이벤트 버블링
 3. 이벤트 터널링


- 직접 이벤트
  : 단일 컨트롤에 등록되는 이벤트 ( 기존 폼 같은... )

- 이벤트 터널링
  : 컨트롤의 비쥬얼 트리에서 이벤트를 발생시킨 컨트롤의 최상위 부모 컨트롤부터 관련 컨트롤까지 Preview 접두어가 명시된 이벤트가 차례로 처리되는 것

- 이벤트 버블링
 : 터널링이 끝난후 이벤트를 발생시킨 컨트롤로부터 부모컨트롤로 Preview 접두어가 명시되지 않은 이벤트가 차례로 발생 처리되는 것

모든 컨트롤에서 이벤트터널링과 이벤트 버블링이 발생하지 않는다.

명령( Command )
 : 특정 컨트롤에 종속적이지 않고 범용적으로 사용할수 있는 이벤트들이 있는데 ,
 잘라내기, 복사, 붙여넣기 등과 같은 이벤트가 대표적인 경우이다.

ICommand 인터페이스를 상속받은 클래스를 정의 한 후 이를 이용한다.

MyCommand.cs
namespace Evt_ICommand
{
    public class MyCommand : ICommand
    {
        #region ICommand 멤버

        public bool CanExecute(object parameter) // 명령을 실행가능한지.
        {
            return true;
        }

        public event EventHandler CanExecuteChanged; // 명령 값이 변화가 발생시...

        public void Execute(object parameter) // 명령처리
        {
            // 파라미터가 null값이 들어옴. ( Test중...)
            Application.Current.Shutdown();
        }

        #endregion
    }
}

Evt-Command.xaml.cs
        <Menu>
            <!-- 1번째 -->
            <MenuItem Header="종료">
                <MenuItem.Command>
                    <MyCommand xmlns="clr-namespace:Evt_ICommand"></MyCommand>
                </MenuItem.Command>
            </MenuItem>

            <!-- 2 번째 -->
            <MenuItem Command="ApplicationCommands.Paste" Header="붙여넣기">               
            </MenuItem>
        </Menu>
 
me: 이렇게 명령을 사용하니까... 명령별로 구분해서 만들고 이벤트대신 명령으로 컨트롤들에 공통 이벤트로 적용이 될만도 한데... 코딩이 좀더 들어갈듯... 좀더 고민해보면 응용이 필요한곳에 적절하게 사용할수 있을듯도 ...

책 Page 260 에 커맨드 종류가 나와있음. 이를 참고!!
  - ApplicationCommands
  - ComponentCommands
  - MediaCommands
  - NavigationCommands
  - EditingCommands

  2번째 명령을 적용해보니 다른 코딩없이 클립보드에서 데이타를 가져와서 붙여넣기가 되었음...


명령바인딩 
 해당 명령이 발생시 이 명령에 대한 별도의 작업을 처리하는 메서드를 호출가능하게 함.
window.xaml
<Window x:Class="Evt_ICommand.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">
    <Window.CommandBindings>
        <CommandBinding Command="ApplicationCommands.Paste"
                        Executed="CommandBinding_Executed"
                        CanExecute="CommandBinding_CanExecute" >
        </CommandBinding>
    </Window.CommandBindings>
    <Grid>
        <Menu>
            <MenuItem Header="종료">
                <MenuItem.Command>
                    <MyCommand xmlns="clr-namespace:Evt_ICommand"></MyCommand>
                </MenuItem.Command>
            </MenuItem>
            <MenuItem Command="ApplicationCommands.Paste" Header="붙여넣기">               
            </MenuItem>
        </Menu>
        <TextBox Margin="0,21,0,0" Name="textBox1" TextWrapping="WrapWithOverflow"/>
    </Grid>
</Window>

window.xaml.cs
    /// <summary>
    /// Window1.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();
        }
        private void CommandBinding_Executed(object sender, ExecutedRoutedEventArgs e)
        {
//               명령에 대한 추가작업
                  MessageBox.Show("붙여넣기 실행!");          
        }
        private void CommandBinding_CanExecute(object sender, CanExecuteRoutedEventArgs e)
        {
//             명령 사용여부
                e.CanExecute = true;
       
}
    }

음... 이게 좀 의문점이 있음.
커서가 TextBox안에 없을때 붙여넣기 메뉴 아이템을 클릭하면 메세지 박스가 실행되지만
TextBox에 커서가 위치된후 붙여넣기 메뉴 아이템 클릭시 메세지 박스가 실행이 안됨.
커서위치 해놓고 Ctrl+V를 눌러도 안됨.

트리거
 : 스타일에 조건을 명시해 적용시키는 데 사용한다.

    <Window.Resources>
        <Style TargetType="{x:Type MenuItem}">
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="Yellow"></Setter>
                </Trigger>
            </Style.Triggers>
        </Style>
    </Window.Resources>

'메뉴아이템에 대한 스타일적용시 IsMouseOver 가 True이면 Background를 Yellow로 변경하여라'
라는 의미의 구문이 된다.

실제 적용해보면 마우스가 메뉴 아이템 위에 올라갔을시 바탕이 노란색으로 바뀌는 것을 볼수 있음.

WPF를 공부시 문법관련해서 외워서 칠 정도가 되려면 좀더 걸리겠다!!
처음 Asp.Net을 공부할때 HTML은 옛날 공부해둔덕에 그만한한 공부에 공들이는 시간을 줄일수 있었다지만.. 이건 뭐... 많긴 많다.


다중 트리거다중 조건 트리거는 책 267~269페이지 참조..

요약 : 다중트리거는 기존 트리거를 몇개 더 붙여놓는거였고...
            <Style.Triggers>
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Background" Value="Yellow"></Setter>
                </Trigger>
             <Trigger Property="IsFocus" Value="True">
                    <Setter Property="Background" Value="Red"></Setter>
                </Trigger>
            </Style.Triggers>

다중 조건 트리거는 여러조건들이 맞아야 스타일을 적용하는 방법임.
 <MultiTriggers>
        <MultiTrigger.Conditions>
             <Condition Property="IsMouseOver" Value="True"/>
             <Condition Property="IsFocus" Value="True"/>
              ...
        </MultiTrigger.Conditions>
         <Setter  스타일 ... >   </Setter>
 </MultiTriggers>

이외에 이벤트 트리거라는것도 있다고 쓰여있음.





- 출처 : .Net 3.5 차세대 개발 프로그래밍 -  책에서 일부 정리 함. ( 저작권 문제시 삭제 할 것임. )
          자세한 내용은 책을 통해 확인하시길...

'# 3) .Net ( Vs 2008 ) > WPF' 카테고리의 다른 글

데이타바인딩(2)  (0) 2009.12.28
데이타바인딩(1)  (0) 2009.12.28
컨트롤  (0) 2009.12.28
스타일  (0) 2009.12.26
리소스  (0) 2009.12.26

 컨트롤은 책에 간단히 설명되있지만... 기존에 .Net 2.0을 공부하듯이 할것임...

'# 3) .Net ( Vs 2008 ) > WPF' 카테고리의 다른 글

데이타바인딩(1)  (0) 2009.12.28
이벤트 종류 & 명령 & 트리거  (0) 2009.12.28
스타일  (0) 2009.12.26
리소스  (0) 2009.12.26
레이아웃 컨트롤  (0) 2009.12.26

스타일
 윈도우에 포함되는 여러 컨트롤에 일괄 적용하거나 여러 프로젝트에서 스타일을 사용하기 위해서
리소스영역에 해당 내용을 기술하고 컨트롤함.

<UserControl x:Class="WpfApplication1.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <UserControl.Resources>       
        <Style x:Key="fontStyle">
            <Setter Property="Control.FontSize" Value="15"></Setter>
        </Style>
    </UserControl.Resources>
    <Grid>
        <!--주석은 이렇게.. -->
        <Button Margin="31,28,47,50" Name="button1" Click="button1_Click" Background="{StaticResource YellowBrush}">Button</Button>
        <Button Style="{StaticResource fontStyle}" Height="44" Margin="68,59,90,0" Name="button2" VerticalAlignment="Top" Click="button2_Click">Button</Button>
    </Grid>
</UserControl>

명시적 스타일 선언
<Style TargetType="{x:Type Button}">
     <Setter Property="Button.FontSize" Value="15"></Setter>
</Style>


버튼에 강제로 스타일을 적용한다.

스타일 상속
        <Style x:Key="fontColor">
            <Setter Property="Control.Background" Value="Yellow"></Setter>
        </Style>
        <Style x:Key="fontStyle" BaseOn="{StaticResource fontColor}">
            <Setter Property="Control.FontSize" Value="15"></Setter>
        </Style>


컨트롤 템플릿
 컨트롤의 외형이나 기타속성들을 템플릿으로 구성하여 적용하는 방법으로 사용함.

- 선언
<Window.Resources>
      <ControlTemplate x:Key="BtnTemplate" >
            <Rectangle Fill="Yellow" />
      </ControlTemplate>
</Window.Resources>

- 적용
<Button Template="{StaticResource BtnTemplate}" />

명시적으로 컨트롤 템플릿 선언하기

<Style TargetType="{x:Type Button}">
     <Setter Property="Template">
         <Setter.Value>
           
  <ControlTemplate>
                      <Rectangle Fill="Yellow" />
                 </ControlTemplate>
        </Setter.Value>
     </Setter>
</Style>



- 출처 : .Net 3.5 차세대 개발 프로그래밍 -  책에서 일부 정리 함. ( 저작권 문제시 삭제 할 것임. )
          자세한 내용은 책을 통해 확인하시길...










'# 3) .Net ( Vs 2008 ) > WPF' 카테고리의 다른 글

이벤트 종류 & 명령 & 트리거  (0) 2009.12.28
컨트롤  (0) 2009.12.28
리소스  (0) 2009.12.26
레이아웃 컨트롤  (0) 2009.12.26
유저컨트롤사용!  (0) 2009.12.26

- 리소스
동적 리소스, 정적리소스로 구분되며 이는 런타임시 리소스의 내용이 변하는지에 대한 차이임.
Key와 Data를 저장하는 컬렉션이다.



정적 리소스 선언
  <Window ... >
      <Window.Resources>
           <SolidColorBrush x:Key="YellowBrush" Color="Yellow" />
      </Window.Resources>

        <Button Background="{StaticResource YellowBrush}" />
 </Window>
<Window.Resources>는 <컨트롤.Resource> 지정이 가능함.
StaticResource 키워드를 이용해 Key에 대한 값을 리소스컬렉션에서 찾아 적용한다.
{} 는 "" 안에 값을 값으로 인식하지 말고 해석하라는 의미임.

동적 리소스 선언
window.xaml
  <Window ... >
        <Button Background="{DynamicResource Window.Background}" Click="button1_Click" />
 </Window>

window.xaml.cs
  private void button1_Click(object sender, RoutedEventArgs e)
  {
        this.Background = Brushes.AliceBlue;                
  }
동적으로 리소스가 변경됨을 볼수 있음.


리소스만을 임의의 파일로 관리하는 방법
새항목 추가 시 : 리소스사전 항목 선택 후 생성

Dictionary1.xaml
<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
    <SolidColorBrush x:Key="YellowBrush" Color="Yellow" />
       ...사용할 리소스 등록...

</ResourceDictionary>

UserControl.xaml
<UserControl x:Class="WpfApplication1.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <UserControl.Resources>
        <ResourceDictionary Source="Dictionary1.xaml" ></ResourceDictionary>
    </UserControl.Resources>
    <Grid>
        <Button Margin="31,28,47,50" Name="button1" Click="button1_Click" Background="{StaticResource YellowBrush}">Button</Button>
        <Button Height="44" Margin="68,59,90,0" Name="button2" VerticalAlignment="Top" Click="button2_Click">Button</Button>
    </Grid>
</UserControl>


리소스 범위
 xml기반의 마크업으로 부모요소안에 자식요소들은 부모요소가 지니는 특징을 모두 갖게 된다.
리소스를 찾을때는 자식부터 상위계층으로 필요한 리소스요소가 있는지 찾아가게 됨.
 파일로 관리시 특정 리소스에 종속적으로 선언된것이 아니므로 모든 컨트롤에서는 리소스 사전에 등록된 리소스를 찾아 적용가능함.


프로그래밍상으로 리소스를 등록 & 찾는 방법
등록
  Resource.Add("YellowBrush" , Brushes.Yellow );
  Resource["YellowBrush"] = Brushes.Yellow;
검색
  적용컨트롤.Background = (Brush)컨트롤.FindResource("YellowBrush" );


어셈블리로 리소스관리하기
   이건 책에 p191 에 자세히 나와있으니 책 참조!



- 출처 : .Net 3.5 차세대 개발 프로그래밍 -  책에서 일부 정리 함. ( 저작권 문제시 삭제 할 것임. )
          자세한 내용은 책을 통해 확인하시길...




'# 3) .Net ( Vs 2008 ) > WPF' 카테고리의 다른 글

컨트롤  (0) 2009.12.28
스타일  (0) 2009.12.26
레이아웃 컨트롤  (0) 2009.12.26
유저컨트롤사용!  (0) 2009.12.26
WPF 응용프로그램 기초  (0) 2009.12.26

패널 형식
StackPanel   : 수직 또는 수평으로 컨트롤을 적제하여 배치함.
DockPanel    : 다섯개의 고정된 위치에 컨트롤을 배치 함.
Grid             : 열과 행을 임의로 정의하여 각 열과 행에 해당컨트롤을 배치함.
Canvas        :  원하는 임의의 위치의 좌표값을 이용하여 컨트롤을 배치함.

*Window : 자식 컨트롤은 어떤것이든 하나의 컨트롤만이 등록될수 있다는 제약조건이 존재함.
             기존의 Form과 다른 점이다.


이에 레이아웃 컨트롤을 적절하게 사용하여 UI를 구성하여야 한다.

- StackPanel  :: 기본 세로정렬
 <StackPanel Orientation="Horizontal"> :: 가로정렬

- DockPanel
 DockPanel.Dock속성을 이용하여 Top, Buttom, Left, Right 위치에 자식컨트롤을 배치 시킴.
ex)
 <DockPanel >
       <Button DockPanel.Dock="Top" />   패널 내에서 상위에 버튼을 위치시킴.
 </DockPanel>
 ** Center라는 속성이 없으며 DockPanel.Dock를 지정하지 않으면 가운데 위치함.
 ** 등록되는 순서에 따라 자식컨트롤위치 및 레이아웃이 변경이 일어남( 기존 Form작업과 같음... )
 
- Grid :: Window 기본 자식요소로 지정되있는 컨트롤임.
  Row설정
  <Grid.RowDefinition>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
            ... 필요한 행수만큼...
  </Grid.RowDefinition>
  Column 설정
  <Grid.ColumnDefinition>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
            ... 필요한 열수만큼...
  </Grid.ColumnDefinition>
  컨트롤 배치
  <Button Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" Grid.RowSpan="2" />
RowSpan과 ColumnSpan 으로 버튼이 그리드내에서 차지할수 있는 영역을 지정할수 있음
HTML테이블처럼...사용할수 있음.

 그리드 간에 크기 공유 방법.
 그리드들의 부모 컨트롤에 속성으로 Grid.IsSharedSizeScope="True" 지정 후
 그리드들의 컬럼들이 크기를 공유할수있도록 그룹을 지정해줌.
  <ColumnDefinition SharedSizeGroup="GroupA" /> 으로 그룹을 지정해줌.

- Canvas :: 컨트롤의 좌측상단의 위치값을 결정후 폭과 높이에 따라 출력시킴.
 <Canvas >
      <Button Canvas.Left="20" Canvas.Top="10" />
      <Button Canvas.Bottom="20" Canvas.Right="10" />
 </Canvas>
 컨트롤의 위치좌표값이 아닌 캔버스 기준으로 컨트롤의 위치를 계산함.
   ex)  Canvas.Left="20" : 캔버스의 Left에서 20만큼 떨어진 위치

- WrapPanel :: ToolBar 아이콘 정렬 되듯이 정렬되는 레이아웃 컨트롤
- UniformGrid :: 각 셀크기가 동일한 Grid 레이아웃.
   <UniFormGrid Columns="2"  Rows="3" /> 2*3 그리드가 나타남.

- ViewBox :: WPF 기본 레이아웃은 아님 ** 하나의 자식컨트롤만 가질수 있음
  자식컨트롤을 자신의 크기만큼 확대해서 보여줌. - 어따 쓰는물건인고?


- 출처 : .Net 3.5 차세대 개발 프로그래밍 -  책에서 일부 정리 함. ( 저작권 문제시 삭제 할 것임. )
          자세한 내용은 책을 통해 확인하시길...

'# 3) .Net ( Vs 2008 ) > WPF' 카테고리의 다른 글

스타일  (0) 2009.12.26
리소스  (0) 2009.12.26
유저컨트롤사용!  (0) 2009.12.26
WPF 응용프로그램 기초  (0) 2009.12.26
WPF 기초...  (0) 2009.12.26

1. 프로젝트 생성 후 새항목 추가로 사용자 정의 컨트롤(WPF) 를 선택 후 컨트롤을 하나 생성 후 정의 함.
2. 윈도우.xaml에  정의컨트롤의 네임스페이스 추가!
   xmlns:my="clr-namespace:사용자정의컨트롤에네임스페이스명"
3. <my:컨트롤명 /> 으로 윈도우.xaml에 컨트롤 추가!!

유저컨트롤.xaml
<UserControl x:Class="WpfApplication1.UserControl1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Height="300" Width="300">
    <Grid>
        <Button Margin="31,28,47,50" Name="button1" Click="button1_Click">Button</Button>
        <Button Height="44" Margin="68,59,90,0" Name="button2" VerticalAlignment="Top" Click="button2_Click">Button</Button>
    </Grid>
</UserControl>

윈도우.xaml
<Window x:Class="WpfApplication1.Window2"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:my="clr-namespace:WpfApplication1"
    Title="Window2" Height="431" Width="503" RenderTransformOrigin="20,180">
    <Grid Height="393" Name="grid1" Width="487">
        <Button Height="44" Margin="12,12,12,0" Name="button1" VerticalAlignment="Top" Opacity="0.2" BorderThickness="1" Click="button1_Click">Button</Button>
        <Rectangle Margin="12,0,0,8.5" Name="rectangle1" Stroke="Black" Opacity="0.5" HorizontalAlignment="Left" Width="150" Height="302.692" VerticalAlignment="Bottom" />       
        <my:UserControl1 Margin="175.875,81.808,18.125,12.789"></my:UserControl1>
    </Grid>
</Window>

** 위에 동일한 색으로 표시해두었음.
    윈폼 작업처럼 도구상자에 안나타남. 위와같이 일일이 쳐야 하는지??? 의문임...

컨트롤을 등록 시 Window와 같은 네임스페이스에 포함되므로 닷넷 프레임워크에서 제공하는 기본 어셈블리에서 클래스를 찾으려 하므로 이와 구별하기위해 아래 네임스페이스를 따로 작성한다.

xmlns:my="clr-namespace:WpfApplication1" 


이는 런타임상에서 해당 클래스를 올바르게 찾을수 있도록 네임스페이스값을 명시해 준다.


- 출처 : .Net 3.5 차세대 개발 프로그래밍 -  책에서 일부 정리 함. ( 저작권 문제시 삭제 할 것임. )
          자세한 내용은 책을 통해 확인하시길...




'# 3) .Net ( Vs 2008 ) > WPF' 카테고리의 다른 글

스타일  (0) 2009.12.26
리소스  (0) 2009.12.26
레이아웃 컨트롤  (0) 2009.12.26
WPF 응용프로그램 기초  (0) 2009.12.26
WPF 기초...  (0) 2009.12.26

Application
 .Run() 응용프로그램 시작
 .Shutdown() 응용프로그램 종료
 .Current 객체 종료시까지 데이타를 공유가능 ( Asp.Net에서의 세션같은 느낌이랄까? )
- 다양한 리소스를 관리함.
 
 .Run()메서드의 호출을 통해 StartupUri 에 명시된 XAML코드를 해석한후 객체를 생성. 출력하는 구조임.

Application 라이프사이클

1. Application 객체 생성
2. Run() 호출
3. Application.StartUp이벤트 발생
4. 응용프로그램을 구성하는 하나 이상의 Window 객체 생성
5. Application.Shutdown() 호출
6. Application.Exit() 호출
7. Run() 종료

<Application x:Class="WpfApplication1.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    StartupUri="Window1.xaml">
    <Application.Resources>
        
    </Application.Resources>
</Application>

startupUri를 통해 시작될 페이지 지정.
또는 StartUp이벤트를 이용해 시작될 페이지를 실행가능

~ app.xaml
<Application x:Class="WpfApplication1.App"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Startup="Application_Startup">
    <Application.Resources>
        
    </Application.Resources>
</Application>

~app.xaml.cs
    /// <summary>
    /// App.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class App : Application
    {
        private void Application_Startup(object sender, StartupEventArgs e)
        {
            Window wd = new Window2();
            wd.Title = "Application_Startup으로 시작";
            wd.Show();
        }
    }
사용자 삽입 이미지
<실행화면>


.Current 사용
  - 저장
  Application.Current.Properties["키명"] = 데이타객체;
  - 읽기
  데이타객체 = Application.Current.Properties["키명"];

----------------------------------------------------------------------------------------
윈도우
  MDI는 지원하지 않음.
  단위화면( Form같은.. )

윈도우 라이프사이클 ( Event )
  1. 해당윈도우 생성자 호출
  2. Initialized()
  3. Activiated()
  4. Loaded()
  5. ContentRendered() = 윈도우가 화면에 최초출력될때 작업완료됨.
  6. 윈도우와 사용자간 이벤트 상호작용 {  ex ) 버튼클릭.... 같은 }
  7. Closing()
  8. Unloaded()
  9. Deatctivated()
  10. Closed()

윈도우 실행
 <Show(),Visibility 프로퍼티 = 모달리스>, < ShowDialog() = 모달 >를  이용함.

관리되는 윈도우..
: Application.Current.Windows 라는 속성으로 현재 응용프로그램에서 사용하는 윈도우를 관리할수 있음.
MDI 를 지원하지 않기에...





- 출처 : .Net 3.5 차세대 개발 프로그래밍 -  책에서 일부 정리 함. ( 저작권 문제시 삭제 할 것임. )
          자세한 내용은 책을 통해 확인하시길...

'# 3) .Net ( Vs 2008 ) > WPF' 카테고리의 다른 글

스타일  (0) 2009.12.26
리소스  (0) 2009.12.26
레이아웃 컨트롤  (0) 2009.12.26
유저컨트롤사용!  (0) 2009.12.26
WPF 기초...  (0) 2009.12.26

XAML  은 XML 기반의 문법을 따르게 된다
  1. 하나의 루트 요소 정의
  2. 대/소문자 구분
  3. 요소의 중첩구조를 허용하지 않음.

루트요소 ( 루트는 1개요소로 정의 됨 )
 1. WINDOW  :  독립 실행형 window 응용프로그램
 2. PAGE : 브라우져에 포함되는 페이지
 3. APPLICATION : 현재 응용프로그램 실행과 관련한 다양한 설정
 
 네임스페이스  : xmlns
 <이름> 홍길동 </이름>
 <이름 xmlns="네임스페이스" > 홍길동 </이름>
  - 네임스페이스 : 기본네임스페이스
  - URI 네임스페이스

 * 네임스페이스 별칭
 <my:이름  xmlns="URI네임스페이스(긴 이름)" > hi </ my:이름 >
  my를 태그 접두어로 사용하여 별칭으로 사용함

ex )
<Window x:Class="~"
    xmlns="http://~"
    xmlns:x="http://~"
    title="타이틀명" >
    <Button Click="Button_Click" Name="Button1" > 확인 </Button>
</Window>

루트 요소는 xmlns 나 xmlns:x로 로더에게 각요소가 속한 네임스페이스 정보를 제공함.

x:Class 의 경우에는 x라는 접두어로 선언된 네임스페이스 포함되므로 Window와는 다른 영역이 됨

접두어 x:
 x:Type   기본클래스의 이름이나 사용자가 직접 정의 하는 클래스의 형식을 명시함.
 x:Key     컬렉션에 컨트롤을 저장할경우 해당 컨트롤이 갖는 고유키 값을 명시함.
 x:Class  CLR의 네임스페이스나 클래스의 이름을 명시함
x:에 대한 정확한 의미는 아직 모르겠음.

 x:Class 는 페이지나 Window 폼을 만들때 사용하는 "네임스페이스.클래스명" 이 들어가는것을
소스상에서 확인할수 있음.





- 출처 : .Net 3.5 차세대 개발 프로그래밍 -  책에서 일부 정리 함. ( 저작권 문제시 삭제 할 것임. )
          자세한 내용은 책을 통해 확인하시길...

'# 3) .Net ( Vs 2008 ) > WPF' 카테고리의 다른 글

스타일  (0) 2009.12.26
리소스  (0) 2009.12.26
레이아웃 컨트롤  (0) 2009.12.26
유저컨트롤사용!  (0) 2009.12.26
WPF 응용프로그램 기초  (0) 2009.12.26