Application/Windows

[WPF] UserControl 만들기

elisom 2024. 2. 23. (Last updated:

 

사용자 정의 컨트롤에 값을 넘기고, Child Control을 넘기는 방법을 기록한다.

 

결과 미리보기

위의 Group Box들과 같이 어떠한 비슷한 컨트롤을 여러 번 사용하게 되는 경우가 많다.

이 때 작성하게 되는 긴 코드를 줄이기 위해 Style을 ResourceDirectory에 정의하여 사용해도 같은 코드가 반복된다.

이를 개선하기 위해 중복되는 사항을 캡슐화할 수 있도록 사용자 정의 컨트롤을 만들어 사용해보겠다.

 

Group Box에는 Title 텍스트와 내용으로 들어갈 Child Control만이 다르고 겉 껍데기는 같다.

Title을 위한 String을 받고, 하늘색으로 칠해진 부분은 Child로 직접 지정할 수 있게 하면 되겠다.

 

사용자 정의 컨트롤 생성

Controls/GroupBox.xaml으로 사용자 정의 컨트롤을 생성한다.

GroupBox.xaml

<UserControl x:Class="ElisomApplication.Controls.GroupBox"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:KLDCManagerApplication.Controls"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Border Style="{StaticResource GroupBorder}">
        <StackPanel Orientation="Vertical">
            <TextBlock Text="{Binding Title}"
                       Style="{StaticResource GroupBorderTitle}"/>
            <ContentPresenter Content="{Binding Child, RelativeSource={RelativeSource AncestorType=UserControl}}"/>
        </StackPanel>
    </Border>
</UserControl>

Border으로 사각형 박스를 그려주고,

안의 내용은 Vertical 정렬의 StackPanel을 사용해 넣는다.

가장 상단에는 Title 값을 바인딩한 TextBlock을 넣고, ContentPresenter을 사용해 Child를 바인딩해 넣는다.

 

DependencyProperty 사용

Controls/GroupBox.xaml.cs에 DependencyProperty를 사용해 프로퍼티를 정의한다.

Controls/GroupBox.xaml.cs

namespace ElisomApplication.Controls
{
    /// <summary>
    /// GroupBox.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class GroupBox : UserControl
    {
        #region DepencyProperty TitleProperty
        public static readonly DependencyProperty TitleProperty =
            DependencyProperty.Register("Title", typeof(string), typeof(GroupBox),
            new PropertyMetadata(string.Empty));

        public string Title { get => (string)GetValue(TitleProperty); set => SetValue(TitleProperty, value); }
        #endregion

        #region DepencyProperty ChildProperty
        public static readonly DependencyProperty ChildProperty =
            DependencyProperty.Register("Child", typeof(UIElement), typeof(GroupBox));

        public UIElement Child { get => (UIElement)GetValue(ChildProperty); set => SetValue(ChildProperty, value); }
        #endregion


        public GroupBox()
        {
            InitializeComponent();
            this.DataContext = this;
        }
    }
}

TitlePropertyChildProperty를 생성한 모습이다.

 

 

사용자 정의 컨트롤 사용

TestView에 생성된 사용자 정의 컨트롤을 넣어 사용해본다.

<UserControl x:Class="ElisomApplication.Views.TestView"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:ElisomApplication.Views"
             xmlns:ctrl="clr-namespace:ElisomApplication.Controls"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <ctrl:GroupBox Title="something">
            <ctrl:GroupBox.Child>
                <Button Content="test"/>
            </ctrl:GroupBox.Child>
        </ctrl:GroupBox>
    </Grid>
</UserControl>

 

해당 컨트롤을 사용하는 공간만큼 늘어나 표시된다💦

 

사용자 정의 컨트롤 크기 맞추기

사용자 정의 컨트롤의 Height가 늘어나지 않고 Child를 감싸는 크기였으면 하여 검색해보니 VerticalAlignment="Top" 속성을 지정하면 된다 하여 수정했다.

<ctrl:GroupBox Title="something" VerticalAlignment="Top">
    <ctrl:GroupBox.Child>
        <Button Content="test"/>
    </ctrl:GroupBox.Child>
</ctrl:GroupBox>

 

바라던 대로 적용된 모습이다😄

 

https://learn.microsoft.com/en-us/answers/questions/35494/how-to-set-width-and-height-to-wrap-to-content-of

 

How to set width and height to wrap to content of UserControl - Microsoft Q&A

Is there a way to wrap the width of a UserControl? The current XAML setup causes the UserControl to stretch to the screen width and this doesn't look great at all. Setting specific widths & heights with numberical values isn't ideal due to differing…

learn.microsoft.com

 

 

 

 

'Application > Windows' 카테고리의 다른 글

[MFC] Dialog에 스크롤 막대 적용하는 방법  (0) 2023.08.24