Skip to content

pjy4617/wpf-study

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

75 Commits
 
 
 
 
 
 
 
 

Repository files navigation

WPF Study

WPF 스터디 시즌 3 문서입니다!


Contributors

Thanks go to these wonderful people (List made with contrib.rocks):


참고 내용

Content


  • 6. ListBox
  • 7. ListBoxItem
  • 8. ItemsControl
  • 9. CustomControl
  • 10. GetContainerItemForOverride
  • 11. AutoGrid.Core
  • 12. CommunityToolkit
  • 13. NugetPackage

  • 14. Bubbling / Tunneling
  • 15. Languages
  • 16. Themes
  • 17. TreeView / TreeViewItem

1. Button

  • ContentControl을 상속한다.
  • 즉, Content 프로퍼티를 갖고 있으며 이는 곧 Button의 내용이다.
<Button Content="버튼"/>

2. ControlTemplate

  • Control 클래스가 갖고 있는 Template 프로퍼티의 타입이다.
  • ControlTemplate을 정의(set value)한다는 것은, 해당 Control의 기존 xaml 구성을 모두 지우고 다시 그리겠다는 의미다.
<Button>
    <Button.Template>
        <!-- ControlTemplate 을 정의하는 순간 본래 Button의 모습을 잃어버린다. -->
        <ControlTemplate>
            <!-- StackPanel, CheckBox, TextBlock 으로 새로운 Button을 그린다. -->
            <StackPanel Orientation="Horizontal">
                <CheckBox/>
                <TextBlock Text="Button"/>
            </StackPanel>
        </ControlTemplate>
    </Button.Template>
</Button>
  • ControlTemplateTargetType 프로퍼티를 갖고 있다.
  • TargetType 으로 새로 그리는 Control의 타입을 알려줘야 해당 Control의 고유 프로퍼티를 호출/연결할 수 있다.
  • ControlTemplateTriggers 프로퍼티를 갖고 있다.
  • Triggers의 타입은 TriggerCollection으로, TriggerBase를 아이템으로 가진다. (4. Trigger 참조)
  • Trigger 를 등록하여 대상 Control의 상태를 감시하고 변경 할 수 있다. (4. Trigger 참조)
<!-- TargetType 으로 Button 지정 -->
<ControlTemplate TargetType="{x:Type Button}">
    ...
    <ControlTemplate.Triggers>
        <!-- Button(ButtonBase)의 고유 프로퍼티인 IsPressed 와 연결 가능 -->
        <!-- IsPressed True 로 변경 시 Background 값 #777777 으로 변경 -->
        <Trigger Property="IsPressed" Value="True">
            <Setter Property="Background" Value="#777777"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
  • 대상 Control 의 프로퍼티와 연결하기 위해 TemplateBinding을 사용한다.
<ControlTemplate TargetType="{x:Type Button}">
    <!-- Button의 BorderBrush, Background 프로퍼티를 연결 -->
    <Border BorderBrush="{TemplateBinding BorderBrush}"
            Background="{TemplateBinding Background}"
            BorderThickness="1"
            Padding="16 6">
    </Border>
    
    <ControlTemplate.Triggers>
        <Trigger Property="IsPressed" Value="True">
            <Setter Property="Background" Value="#777777"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
  • 내부 Control에 Name을 부여하여 내부에서 직접 접근하는 방법도 있다.
<ControlTemplate TargetType="{x:Type Button}">
    <!-- 내부 Control에 border Name 부여 -->
    <!-- Background 연결 해제 -->
    <Border x:Name="border"
            BorderBrush="{TemplateBinding BorderBrush}"
            Background="#eeeeee"
            BorderThickness="1"
            Padding="16 6">
    </Border>
    
    <ControlTemplate.Triggers>
        <Trigger Property="IsPressed" Value="True">
            <!-- TargetName 으로 border를 지정하여 Border Background에 직접 접근 -->
            <Setter TargetName="border" Property="Background" Value="#777777"/>
        </Trigger>
    </ControlTemplate.Triggers>
</ControlTemplate>
  • 대상 ControlContentControl을 상속하고 있다면, ContentPresenter를 통해 ContentTemplate을 바인딩 할 수 있다.
<ControlTemplate TargetType="{x:Type Button}">
    <!-- 내부 Control에 border Name 부여 -->
    <!-- Background 연결 해제 -->
    <Border x:Name="border"
            BorderBrush="{TemplateBinding BorderBrush}"
            Background="{TemplateBinding Background}"
            BorderThickness="1"
            Padding="16 6">
        <!-- ContentPresenter 로 Content 바인딩 -->
        <ContentPresenter/>
        <!-- 아래 코드와 같은 의미
        <ContentPresenter ContentTemplate="{TemplateBinding ContentTemplate}"/>
        -->
    </Border>
</ControlTemplate>

3. DataTemplate

  • ContentControl을 상속 받는 클래스의 ContentTemplate을 재정의 해줌

    • Content를 재정의하고 있으며, ContentControl을 상속 받는 WindowButton이나 모두 같은 원리로 동작한다.(ContentControl을 상속 받는 모든 개체)
    • Button, ToggleButton, CheckBox, RadioButton 등에 모두 같은 DataTemplate이 적용된 것을 볼 수 있다.
  • 실행 화면 (좌측부터 Button, ToggleButton, CheckBox, RadioButton - 같은 DataTemplate을 사용하고 있다.)

DataTemplate Test

<!-- 위 화면의 xaml 코드 -->
    <Window.Resources>
        <DataTemplate x:Key="ButtonContentTemplate">
            <Grid>
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="50"/>
                    <ColumnDefinition Width="70"/>
                </Grid.ColumnDefinitions>
                <TextBlock Grid.Row="0" Grid.Column="0" Text="Text1"/>
                <TextBlock Grid.Row="1" Grid.Column="1" Text="Text2"/>
            </Grid>
        </DataTemplate>
    </Window.Resources>
    <StackPanel Orientation="Horizontal" HorizontalAlignment="Left" VerticalAlignment="Top">
        <Button Margin="5"
                ContentTemplate="{StaticResource ButtonContentTemplate}"/>
        <ToggleButton Margin="5"
                  ContentTemplate="{StaticResource ButtonContentTemplate}"/>
        <CheckBox Margin="5"
                  ContentTemplate="{StaticResource ButtonContentTemplate}"/>
        <RadioButton Margin="5"
                     ContentTemplate="{StaticResource ButtonContentTemplate}"/>
    </StackPanel>

4. Trigger

  • TriggerBase를 상속한다.
  • 조건을 설정하고, 조건 만족시 변경할 상태(or Action)를 정의.
  • 조건 불만족 시 이전 상태로 복귀.
  • 주요 프로퍼티.
Name Type Note
Property DependencyProperty 감시 대상(Control)의 Property(DependencyProperty)
Value object 설정한 Property 와 비교할 값
Setters SetterBaseCollection Trigger 조건 만족 시 적용할 Setter 목록 (복수 Setter 설정 가능)
<Button Content="버튼">
    <Button.Style>
        <Style TargetType="{x:Type Button}">
            <Style.Triggers>
            
                <!-- Trigger 1. 감시 대상 Button의 IsMouseOver 값이 True 일 때 -->
                <!-- Foreground = Red, Cursor = Hand 로 변경 -->
                <Trigger Property="IsMouseOver" Value="True">
                    <Setter Property="Foreground" Value="Red"/>
                    <Setter Property="Cursor" Value="Hand"/>
                </Trigger>
                
                <!-- Trigger 2. 감시 대상 Button의 IsPressed 값이 True 일 때 -->
                <!-- Foreground = White 로 변경 -->
                <Trigger Property="IsPressed" Value="True">
                    <Setter Property="Foreground" Value="White"/>
                    
                    <!-- Setters 태그 생략 가능
                    <Trigger.Setters>
                        <Setter Property="Foreground" Value="White"/>
                    </Trigger.Setters>
                    -->
                </Trigger>
                
            </Style.Triggers>
        </Style>
    </Button.Style>
</Button>

5. ContentControl

  • Content 프로퍼티를 갖고 있다.
  • Content 타입은 object 로 다른 Control 을 넣을 수 있다.
<!-- case 1. text content-->
<Button Content="버튼"/>

<!-- case 2. control content -->
<Button>
    <Button.Content>
        <StackPanel Orientation="Horizontal">
            <CheckBox/>
            <TextBlock Text="버튼"/>
        </StackPanel>
    </Button.Content>
</Button>
  • Content 로 문자열만 입력된 경우는 내부적으로 TextBlock이 추가됐다고 볼 수 있다.
<!-- case 1 -->
<Button Content="버튼"/>

<!-- case 2 -->
<Button>
    <Button.Content>
        버튼
    </Button.Content>
</Button>

<!-- case 3 -->
<Button>
    <Button.Content>
        <TextBlock Text="버튼"/>
    </Button.Content>
</Button>
  • ContentTemplate 프로퍼티를 갖고 있다.
  • ContentTemplate 타입은 DateTemplate 으로 Resource에 정의한 DataTemplate을 넣을 수 있다.
<Window.Resources>
    <!-- DataTemplate example -->
    <DataTemplate x:Key="buttonContentTemplate">
        <TextBlock Text="버튼"/>
    </DataTemplate>
</Window.Resources>

<Grid>
    <!-- Use ContentTemplate -->
    <Button ContentTemplate="{StaticResource buttonContentTemplate}"/>    
</Grid>
  • Xaml 에서 Content 태그는 생략 가능하다.
<Button>
    <Button.Content>
        버튼
    </Button.Content>
</Button>

<!-- Content Tag 생략 -->
<Button>
    버튼
</Button>
  • ContentControl 클래스를 상속받는 Control 목록 (작성 중...)
클래스 부모 클래스
Button ButtonBase
CheckBox ContentControl
RadioButton ContentControl
ToggleButton ContentControl
ListBoxItem ContentControl
Label ContentControl
ComboBoxItem ContentControl
ListViewItem ContentControl
TreeViewItem ContentControl
GroupBox ContentControl
Window ContentControl
UserControl ContentControl
ScrollViewer ContentControl

6. ListBox

  • 다음과 같은 상속 관계를 가진다
    • ItemsControl -> Selector -> ListBox
  • 주요 프로퍼티
Name Type Content Note
ItemsSource IEnumerable ListBoxItem을 생성하기 위한 컬렉션 ItemsControl에서 상속됨
ItemTemplate DataTemplate ListBoxItem의 ContentTemplate을 재정의하기 위한 DataTemplate ItemsControl에서 상속됨 (3. DataTemplate 참조)
ItemContainerStyle Style ListBoxItem의 Style ItemsControl에서 상속됨
DisplayMemberPath string ListBoxItem의 Content로 표시할 Path 이름. 바인딩 된 아이템 Source 객체의 프로퍼티 중 Content로 표시할 프로퍼티 이름으로 설정한다. ItemsControl에서 상속됨
SelectedItem object
  • 선택된 첫번째 아이템
    (여러개 선택 시 처음 선택된 아이템 하나만 반환)
  • 선택된 항목이 없는 경우 null 반환
Selector에서 상속됨
SelectionMode SelectionMode(Enum) ListBox 의 선택 동작 정의
  • Single : 하나만 선택 가능
  • Multiple : 한정자 키 누르지 않고 여러개 선택 가능
  • Extended : Shift 키 누른 상태로 여러개 선택 가능

7. ListBoxItem

  • 다음과 같은 상속 관계를 가진다
  • ListBoxItemTemplate을 설정하여 Content를 재정의할 수 있다.
  • ListBoxItemContainerStyle 설정하여 Style을 적용할 수 있다.

14. Bubbling / Tunneling

  • 이벤트의 순서는 Tunneling -> Bubbling 순서로 발생한다.

Tunneling

  • Tunneling 이벤트는 UIElementPreview 접두사가 붙은 이벤트이다.
  • Tunneling 이벤트는 Tunneling 이벤트를 처리하는 Handler가 없으면 Bubbling 이벤트를 처리하는 Handler를 찾는다.

Bubbling

  • Bubbling 이벤트는 Tunneling 이벤트와 반대로 UIElementPreview 접두사가 붙지 않은 이벤트이다.

Blog(순서 a ~ Z , ㄱ ~ ㅎ)

  • Arong Note. : 일상 생활 내용 및 IT 프로그램 기술 관련 정보 정리하는 공간
  • jamesnet214. : WPF 개발 내용 및 인생 팁
  • kjun. : C# 개발 내용 정리
  • Kratos. : C# 관련

About

No description, website, or topics provided.

Resources

License

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published

Languages

  • C# 100.0%