WPF ProgressBar 모양을 배터리로 만드는 법 궁금합니다.

ProgressBar를 처음 써보면서 배터리 모양으로 만들어 보려했는데

아직 배운지 얼마 안되서 어떻게 해야할지 감이 안 잡힙니다…

ProgressBar의 기본 템플릿을 수정해서 배터리 느낌을 만들고 싶었는데

모양만 그럴싸하게 만들다보니깐 배터리 느낌을 Border로 나누다보니 스타일에서 width값을 바꾸면 또 깨지고 그러네요…

혹시 어떻게 만들어야할지 조언좀 주실 수 있나요

그리고 혹시 ProgressBar 끝에 건전지 처럼 볼록한 느낌을 넣고싶은데
방법이 있다면 알고싶습니다.

<Style x:Key="ProgressBarStyle1Battery" TargetType="{x:Type ProgressBar}">
    <Setter Property="Foreground" Value="{StaticResource ProgressBar.Progress}"/>
    <Setter Property="Background" Value="Transparent"/>
    <Setter Property="BorderBrush" Value="{StaticResource ProgressBar.Border}"/>
    <Setter Property="BorderThickness" Value="1"/>

    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type ProgressBar}">
                <Grid x:Name="TemplateRoot">
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Determinate"/>
                            <VisualState x:Name="Indeterminate">
                                <Storyboard RepeatBehavior="Forever">
                                    <DoubleAnimationUsingKeyFrames Storyboard.TargetName="Animation" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
                                        <EasingDoubleKeyFrame KeyTime="0" Value="0.25"/>
                                        <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.25"/>
                                        <EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.25"/>
                                    </DoubleAnimationUsingKeyFrames>
                                    <PointAnimationUsingKeyFrames Storyboard.TargetName="Animation" Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)">
                                        <EasingPointKeyFrame KeyTime="0" Value="-0.5,0.5"/>
                                        <EasingPointKeyFrame KeyTime="0:0:1" Value="0.5,0.5"/>
                                        <EasingPointKeyFrame KeyTime="0:0:2" Value="1.5,0.5"/>
                                    </PointAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>
                    <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1"/>
                    <Rectangle x:Name="PART_Track"/>
                    <Grid x:Name="PART_Indicator" ClipToBounds="true" HorizontalAlignment="Left">
                        <Border Background="{StaticResource ProgressBar.Progress}" BorderBrush="{StaticResource ProgressBar.Progress}" BorderThickness="0" CornerRadius="0.3" Margin="1,1,0,1"/>

                    </Grid>
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="1*"/>
                            <ColumnDefinition Width="1*"/>
                            <ColumnDefinition Width="1*"/>
                            <ColumnDefinition Width="1*"/>
                        </Grid.ColumnDefinitions>

                        <Border Padding="0" BorderBrush="White" BorderThickness="1" Width="15" Height="15" CornerRadius="1,0,0,1" Margin="0,0,0,0" Grid.Column="0"/>
                        <Border Padding="0" BorderBrush="White" BorderThickness="1" Width="15" Height="15" CornerRadius="0.0" Margin="-1,0,0,0" Grid.Column="1"/>
                        <Border Padding="0" BorderBrush="White" BorderThickness="1" Width="16" Height="15" CornerRadius="0,0,0,0" Margin="-1,0,0,0" Grid.Column="2"/>
                        <Border Padding="0" BorderBrush="White" BorderThickness="1" Width="16" Height="15" CornerRadius="0,1,1,0" Margin="-1,0,0,0" Grid.Column="3"/>

                        
                    </Grid>

                    <Grid>
                        <Border Background="White" Width="4" Height="7" BorderBrush="White" BorderThickness="1" CornerRadius="0,1,1,0" Margin="50,0,0,0"/>
                    </Grid>

                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="Orientation" Value="Vertical">
                        <Setter Property="LayoutTransform" TargetName="TemplateRoot">
                            <Setter.Value>
                                <RotateTransform Angle="-90"/>
                            </Setter.Value>
                        </Setter>
                    </Trigger>

                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

제가 사용한 기본 템플릿 입니다.

width 60 height 15로할땐 그나마 비슷하게 나오긴 하는데 크기를 바꾸면 다 깨지네요…
111

대충 이런 모양으로 만들고 싶습니다.

2개의 좋아요

볼록한 느낌이라는게 모서리 부분을 둥글게 하고싶으신다는건가요?

1개의 좋아요

오른쪽 끝에 작은 네모부분을 추가하고싶습니다.

4번째 네모 오른쪽에 조금 튀어나온건 없다고 생각해주시면 감사합니다

1개의 좋아요

image
요런느낌은 되는데 맞나요?

3개의 좋아요

네 맞습니다!

1개의 좋아요
  1. 마지막 둥근 부분을 제외 한 각 칸(Border)값들의 Width값과 Height값의
    사이즈를 지정해주실 필요가없습니다. (프로그레스에서 이미 전체 사이즈를 지정해주셨기 때문에)

  2. 마지막 칸의 경우 HorizontalAlignment = Left처리와 Margin값 -1,0,0,0으로 변경해주시면됩니다.

수정된 Grid 코드입니다.
확인해보세요!

BorderBrush=“{TemplateBinding BorderBrush}” 부분은
BorderBrush="Black"으로 대체하셔서 쓰셔도 무방합니다

<Grid x:Name="TemplateRoot">
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

    <Border
        Grid.Column="0"
        Margin="0,0,0,0"
        Padding="0"
        BorderBrush="{TemplateBinding BorderBrush}"
        BorderThickness="1"
        CornerRadius="1,0,0,1" />
    <Border
        Grid.Column="1"
        Margin="-1,0,0,0"
        Padding="0"
        BorderBrush="{TemplateBinding BorderBrush}"
        BorderThickness="1"
        CornerRadius="0.0" />
    <Border
        Grid.Column="2"
        Margin="-1,0,0,0"
        Padding="0"
        BorderBrush="{TemplateBinding BorderBrush}"
        BorderThickness="1"
        CornerRadius="0,0,0,0" />
    <Border
       Grid.Column="3"
       Margin="-1,0,0,0"
       Padding="0"
       BorderBrush="{TemplateBinding BorderBrush}"
       BorderThickness="1"
       CornerRadius="0,1,1,0" />
    <Border
        Grid.Column="4"
        Width="4"
        Height="7"
        Margin="-1,0,0,0"
        HorizontalAlignment="Left"
        BorderBrush="{TemplateBinding BorderBrush}"
        BorderThickness="1"
        CornerRadius="0,1,1,0" />
</Grid>
6개의 좋아요

혹시 아직 스타일이 잘 이해 안되서 그러는데 제 스타일 코드에서 어디 부분에 넣어야 할까요…?

<Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="1*"/>
                            <ColumnDefinition Width="1*"/>
                            <ColumnDefinition Width="1*"/>
                            <ColumnDefinition Width="1*"/>
                        </Grid.ColumnDefinitions>

                        <Border Padding="0" BorderBrush="White" BorderThickness="1" Width="15" Height="15" CornerRadius="1,0,0,1" Margin="0,0,0,0" Grid.Column="0"/>
                        <Border Padding="0" BorderBrush="White" BorderThickness="1" Width="15" Height="15" CornerRadius="0.0" Margin="-1,0,0,0" Grid.Column="1"/>
                        <Border Padding="0" BorderBrush="White" BorderThickness="1" Width="16" Height="15" CornerRadius="0,0,0,0" Margin="-1,0,0,0" Grid.Column="2"/>
                        <Border Padding="0" BorderBrush="White" BorderThickness="1" Width="16" Height="15" CornerRadius="0,1,1,0" Margin="-1,0,0,0" Grid.Column="3"/>

                        
                    </Grid>

이 부분에 넣으면 위쪽 기본 스타일이랑 겹치고
TemplateRoot 부분에 넣으면 ProgressBar에서 value를 늘리면 배터리를 초과해서 게이지가 차고.

<Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" CornerRadius="1"/>

이 부분에 추가를 하면 모양은 제대로 나오는데 value를 100으로 하면 한칸밖에 안 차는데
혹시 알려주실 수 있나요

1개의 좋아요

image

기존 TemplateRoot 아래에 있는 이부분을 대체해서 그렸다고 생각해보시면 좋습니다.

<Border
    Background="{TemplateBinding Background}"
    BorderBrush="{TemplateBinding BorderBrush}"
    BorderThickness="{TemplateBinding BorderThickness}" />

아래 코드는 전체 코드입니다.

 <ControlTemplate TargetType="{x:Type ProgressBar}">
     <Grid x:Name="TemplateRoot">
         <Grid>
             <Grid.ColumnDefinitions>
                 <ColumnDefinition Width="*" />
                 <ColumnDefinition Width="*" />
                 <ColumnDefinition Width="*" />
                 <ColumnDefinition Width="*" />
                 <ColumnDefinition Width="*" />
             </Grid.ColumnDefinitions>
             <Border
                 Grid.Column="0"
                 Margin="0,0,0,0"
                 Padding="0"
                 Background="Transparent"
                 BorderBrush="{TemplateBinding BorderBrush}"
                 BorderThickness="1"
                 CornerRadius="1,0,0,1" />
             <Border
                 Grid.Column="1"
                 Margin="-1,0,0,0"
                 Padding="0"
                 Background="Transparent"
                 BorderBrush="{TemplateBinding BorderBrush}"
                 BorderThickness="1"
                 CornerRadius="0.0" />
             <Border
                 Grid.Column="2"
                 Margin="-1,0,0,0"
                 Padding="0"
                 Background="Transparent"
                 BorderBrush="{TemplateBinding BorderBrush}"
                 BorderThickness="1"
                 CornerRadius="0,0,0,0" />
             <Border
                 Grid.Column="3"
                 Margin="-1,0,0,0"
                 Padding="0"
                 Background="Transparent"
                 BorderBrush="{TemplateBinding BorderBrush}"
                 BorderThickness="1"
                 CornerRadius="0,1,1,0" />
             <Border
                 Grid.Column="4"
                 Width="4"
                 Height="7"
                 Margin="-1,0,0,0"
                 HorizontalAlignment="Left"
                 BorderBrush="{TemplateBinding BorderBrush}"
                 BorderThickness="1"
                 CornerRadius="0,1,1,0" />
         </Grid>
         <Rectangle x:Name="PART_Track" />
         <Grid
             x:Name="PART_Indicator"
             HorizontalAlignment="Left"
             ClipToBounds="true">
             <Rectangle x:Name="Indicator" Fill="{TemplateBinding Foreground}" />
             <Rectangle
                 x:Name="Animation"
                 Fill="{TemplateBinding Foreground}"
                 RenderTransformOrigin="0.5,0.5">
                 <Rectangle.RenderTransform>
                     <TransformGroup>
                         <ScaleTransform />
                         <SkewTransform />
                         <RotateTransform />
                         <TranslateTransform />
                     </TransformGroup>
                 </Rectangle.RenderTransform>
             </Rectangle>
         </Grid>
         <VisualStateManager.VisualStateGroups>
             <VisualStateGroup x:Name="CommonStates">
                 <VisualState x:Name="Determinate" />
                 <VisualState x:Name="Indeterminate">
                     <Storyboard RepeatBehavior="Forever">
                         <DoubleAnimationUsingKeyFrames Storyboard.TargetName="Animation" Storyboard.TargetProperty="(UIElement.RenderTransform).(TransformGroup.Children)[0].(ScaleTransform.ScaleX)">
                             <EasingDoubleKeyFrame KeyTime="0" Value="0.25" />
                             <EasingDoubleKeyFrame KeyTime="0:0:1" Value="0.25" />
                             <EasingDoubleKeyFrame KeyTime="0:0:2" Value="0.25" />
                         </DoubleAnimationUsingKeyFrames>
                         <PointAnimationUsingKeyFrames Storyboard.TargetName="Animation" Storyboard.TargetProperty="(UIElement.RenderTransformOrigin)">
                             <EasingPointKeyFrame KeyTime="0" Value="-0.5,0.5" />
                             <EasingPointKeyFrame KeyTime="0:0:1" Value="0.5,0.5" />
                             <EasingPointKeyFrame KeyTime="0:0:2" Value="1.5,0.5" />
                         </PointAnimationUsingKeyFrames>
                     </Storyboard>
                 </VisualState>
             </VisualStateGroup>
         </VisualStateManager.VisualStateGroups>
     </Grid>
     <ControlTemplate.Triggers>
         <Trigger Property="Orientation" Value="Vertical">
             <Setter TargetName="TemplateRoot" Property="LayoutTransform">
                 <Setter.Value>
                     <RotateTransform Angle="-90" />
                 </Setter.Value>
             </Setter>
         </Trigger>
         <Trigger Property="IsIndeterminate" Value="true">
             <Setter TargetName="Indicator" Property="Visibility" Value="Collapsed" />
         </Trigger>
     </ControlTemplate.Triggers>
 </ControlTemplate>
2개의 좋아요

감사합니다 모양이 제대로 나옵니다

혹시 적용하고서 나온 문제인데 Value 값을 넣으면서 알게된건데

value값이랑 배터리의 크기랑 맞지 않는데 혹시 어디 수정해야할까요?

333

적용 해보았더니 위처럼 나오네요…

222
이런 식으로 크기에 맞게 하고싶습니다…!

1개의 좋아요

프로그레스바 자체 태생적으로 Rectangle로 늘려가는 구조이다보니

원하시는 구도처럼 자유롭게 그려보려면
커스텀컨트롤로 아예 새로 만드셔야할거같아요!

1개의 좋아요

아하 감사합니다!

한번 만들어보겠습니다!

1개의 좋아요

PART_Track, PART_Indicator를 TemplateRoot 에 넣고 Grid.ColumnSpan=“4” 로 설정하면 되지 않을까 합니다.

3개의 좋아요