WPF 응용 프로그램을 Windows 7에서도 Metro 스타일로 보이게 만들까요? (윈도우 크롬 / 테마 / 테마)


123

새로운 Office Suite 및 Visual Studio의 창 크롬이 마음에 듭니다.

여기에 이미지 설명 입력

물론 Windows 7 용 응용 프로그램을 개발 중이지만이 스타일을 에뮬레이션하는 빠르고 쉬운 방법 (WPF 스타일 또는 Windows 라이브러리 읽기)이 있는지 궁금합니다. 나는 과거에 윈도우 크롬 스타일링을 해봤지만 제대로 보이고 제대로 작동하도록하는 것은 정말 까다 롭다.

내 WPF 응용 프로그램에 "최신 UI"모양과 느낌을 추가 할 기존 템플릿이나 라이브러리가 있는지 아는 사람이 있습니까?


8
이 가이드 / NuGet 패키지가 도움이 될 수 있습니다. MahaApps Metro Metro Look & Feel로 WPF 앱을 만들기위한 스타일 및 컨트롤 집합이 포함되어 있습니다.
Oliver Vogel

책, 도구, 소프트웨어 라이브러리, 자습서 또는 기타 오프 사이트 리소스 를 추천하거나 찾도록 요청하는 질문 은 의견이있는 답변과 스팸을 유도하는 경향이 있으므로 Stack Overflow에서 주제를 벗어납니다. 대신 문제와 해결을 위해 지금까지 수행 한 작업을 설명하십시오.
스콧 Solmer

답변:


149

내가 한 일은 나만의 창과 스타일을 만드는 것이 었습니다. 나는 모든 것을 제어하는 ​​것을 좋아하고 일부 외부 라이브러리에서 창을 사용하는 것을 원하지 않았기 때문입니다. 이미 언급 한 MahApps.Metro를 GitHub 에서 살펴 보았습니다.

MahApps

GitHub의 매우 멋진 Modern UI도 있습니다 . (.NET4.5 만 해당)

최신 UI

Elysium 이 하나 더 있지만 나는 이것을 실제로 시도하지 않았습니다.

엘리시움

내가 한 스타일은 이것들에서 어떻게되는지 보았을 때 정말 쉬웠습니다. 이제 나만의 Window가 있고 xaml로 원하는 모든 작업을 수행 할 수 있습니다.이게 제가 직접 만든 주된 이유입니다. 그리고 저는 여러분을 위해 하나 더 만들었습니다. :) Modern UI 를 탐색하지 않고서는 할 수 없을 것이라고 말하고 싶습니다 . 그것은 큰 도움이되었습니다. VS2012 창처럼 보이게 만들려고했습니다. 이렇게 생겼습니다.

MyWindow

다음은 코드입니다 (.NET4.5를 대상으로합니다).

public class MyWindow : Window
{

    public MyWindow()
    {
        this.CommandBindings.Add(new CommandBinding(SystemCommands.CloseWindowCommand, this.OnCloseWindow));
        this.CommandBindings.Add(new CommandBinding(SystemCommands.MaximizeWindowCommand, this.OnMaximizeWindow, this.OnCanResizeWindow));
        this.CommandBindings.Add(new CommandBinding(SystemCommands.MinimizeWindowCommand, this.OnMinimizeWindow, this.OnCanMinimizeWindow));
        this.CommandBindings.Add(new CommandBinding(SystemCommands.RestoreWindowCommand, this.OnRestoreWindow, this.OnCanResizeWindow));
    }

    private void OnCanResizeWindow(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = this.ResizeMode == ResizeMode.CanResize || this.ResizeMode == ResizeMode.CanResizeWithGrip;
    }

    private void OnCanMinimizeWindow(object sender, CanExecuteRoutedEventArgs e)
    {
        e.CanExecute = this.ResizeMode != ResizeMode.NoResize;
    }

    private void OnCloseWindow(object target, ExecutedRoutedEventArgs e)
    {
        SystemCommands.CloseWindow(this);
    }

    private void OnMaximizeWindow(object target, ExecutedRoutedEventArgs e)
    {
        SystemCommands.MaximizeWindow(this);
    }

    private void OnMinimizeWindow(object target, ExecutedRoutedEventArgs e)
    {
        SystemCommands.MinimizeWindow(this);
    }

    private void OnRestoreWindow(object target, ExecutedRoutedEventArgs e)
    {
        SystemCommands.RestoreWindow(this);
    }
}

그리고 여기 리소스 :

<BooleanToVisibilityConverter x:Key="bool2VisibilityConverter" />

<Color x:Key="WindowBackgroundColor">#FF2D2D30</Color>
<Color x:Key="HighlightColor">#FF3F3F41</Color>
<Color x:Key="BlueColor">#FF007ACC</Color>
<Color x:Key="ForegroundColor">#FFF4F4F5</Color>

<SolidColorBrush x:Key="WindowBackgroundColorBrush" Color="{StaticResource WindowBackgroundColor}"/>
<SolidColorBrush x:Key="HighlightColorBrush" Color="{StaticResource HighlightColor}"/>
<SolidColorBrush x:Key="BlueColorBrush" Color="{StaticResource BlueColor}"/>
<SolidColorBrush x:Key="ForegroundColorBrush" Color="{StaticResource ForegroundColor}"/>

<Style x:Key="WindowButtonStyle" TargetType="{x:Type Button}">
    <Setter Property="Foreground" Value="{DynamicResource ForegroundColorBrush}" />
    <Setter Property="Background" Value="Transparent" />
    <Setter Property="HorizontalContentAlignment" Value="Center" />
    <Setter Property="VerticalContentAlignment" Value="Center" />
    <Setter Property="Padding" Value="1" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type Button}">
                <Grid Background="{TemplateBinding Background}">
                    <ContentPresenter x:Name="contentPresenter"
                          HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
                          VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
                          SnapsToDevicePixels="{TemplateBinding SnapsToDevicePixels}"
                          Margin="{TemplateBinding Padding}"
                          RecognizesAccessKey="True" />
                </Grid>
                <ControlTemplate.Triggers>
                    <Trigger Property="IsMouseOver" Value="True">
                        <Setter Property="Background" Value="{StaticResource HighlightColorBrush}" />
                    </Trigger>
                    <Trigger Property="IsPressed" Value="True">
                        <Setter Property="Background" Value="{DynamicResource BlueColorBrush}" />
                    </Trigger>
                    <Trigger Property="IsEnabled" Value="false">
                        <Setter TargetName="contentPresenter" Property="Opacity" Value=".5" />
                    </Trigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

<Style x:Key="MyWindowStyle" TargetType="local:MyWindow">
    <Setter Property="Foreground" Value="{DynamicResource ForegroundColorBrush}" />
    <Setter Property="Background" Value="{DynamicResource WindowBackgroundBrush}"/>
    <Setter Property="ResizeMode" Value="CanResizeWithGrip" />
    <Setter Property="UseLayoutRounding" Value="True" />
    <Setter Property="TextOptions.TextFormattingMode" Value="Display" />
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:MyWindow">
                <Border x:Name="WindowBorder" Margin="{Binding Source={x:Static SystemParameters.WindowNonClientFrameThickness}}" Background="{StaticResource WindowBackgroundColorBrush}">
                    <Grid>
                        <Border BorderThickness="1">
                            <AdornerDecorator>
                                <Grid x:Name="LayoutRoot">
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="25" />
                                        <RowDefinition Height="*" />
                                        <RowDefinition Height="15" />
                                    </Grid.RowDefinitions>
                                    <ContentPresenter Grid.Row="1" Grid.RowSpan="2" Margin="7"/>
                                    <Rectangle x:Name="HeaderBackground" Height="25" Fill="{DynamicResource WindowBackgroundColorBrush}" VerticalAlignment="Top" Grid.Row="0"/>
                                    <StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" WindowChrome.IsHitTestVisibleInChrome="True" Grid.Row="0">
                                        <Button Command="{Binding Source={x:Static SystemCommands.MinimizeWindowCommand}}" ToolTip="minimize" Style="{StaticResource WindowButtonStyle}">
                                            <Button.Content>
                                                <Grid Width="30" Height="25" RenderTransform="1,0,0,1,0,1">
                                                    <Path Data="M0,6 L8,6 Z" Width="8" Height="7" VerticalAlignment="Center" HorizontalAlignment="Center"
                                                        Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" StrokeThickness="2"  />
                                                </Grid>
                                            </Button.Content>
                                        </Button>
                                        <Grid Margin="1,0,1,0">
                                            <Button x:Name="Restore" Command="{Binding Source={x:Static SystemCommands.RestoreWindowCommand}}" ToolTip="restore" Visibility="Collapsed" Style="{StaticResource WindowButtonStyle}">
                                                <Button.Content>
                                                    <Grid Width="30" Height="25" UseLayoutRounding="True" RenderTransform="1,0,0,1,.5,.5">
                                                        <Path Data="M2,0 L8,0 L8,6 M0,3 L6,3 M0,2 L6,2 L6,8 L0,8 Z" Width="8" Height="8" VerticalAlignment="Center" HorizontalAlignment="Center"
                                                            Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" StrokeThickness="1"  />
                                                    </Grid>
                                                </Button.Content>
                                            </Button>
                                            <Button x:Name="Maximize" Command="{Binding Source={x:Static SystemCommands.MaximizeWindowCommand}}" ToolTip="maximize" Style="{StaticResource WindowButtonStyle}">
                                                <Button.Content>
                                                    <Grid Width="31" Height="25">
                                                        <Path Data="M0,1 L9,1 L9,8 L0,8 Z" Width="9" Height="8" VerticalAlignment="Center" HorizontalAlignment="Center"
                                                            Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" StrokeThickness="2"  />
                                                    </Grid>
                                                </Button.Content>
                                            </Button>
                                        </Grid>
                                        <Button Command="{Binding Source={x:Static SystemCommands.CloseWindowCommand}}" ToolTip="close"  Style="{StaticResource WindowButtonStyle}">
                                            <Button.Content>
                                                <Grid Width="30" Height="25" RenderTransform="1,0,0,1,0,1">
                                                    <Path Data="M0,0 L8,7 M8,0 L0,7 Z" Width="8" Height="7" VerticalAlignment="Center" HorizontalAlignment="Center"
                                                        Stroke="{Binding Foreground, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=Button}}" StrokeThickness="1.5"  />
                                                </Grid>
                                            </Button.Content>
                                        </Button>
                                    </StackPanel>
                                    <TextBlock x:Name="WindowTitleTextBlock" Grid.Row="0" Text="{TemplateBinding Title}" HorizontalAlignment="Left" TextTrimming="CharacterEllipsis" VerticalAlignment="Center"  Margin="8 -1 0 0"  FontSize="16"  Foreground="{TemplateBinding Foreground}"/>
                                    <Grid Grid.Row="2">
                                        <Path x:Name="ResizeGrip" Visibility="Collapsed" Width="12" Height="12" Margin="1" HorizontalAlignment="Right"
                                        Stroke="{StaticResource BlueColorBrush}" StrokeThickness="1" Stretch="None" Data="F1 M1,10 L3,10 M5,10 L7,10 M9,10 L11,10 M2,9 L2,11 M6,9 L6,11 M10,9 L10,11 M5,6 L7,6 M9,6 L11,6 M6,5 L6,7 M10,5 L10,7 M9,2 L11,2 M10,1 L10,3" />
                                    </Grid>
                                </Grid>
                            </AdornerDecorator>
                        </Border>
                        <Border BorderBrush="{StaticResource BlueColorBrush}" BorderThickness="1" Visibility="{Binding IsActive, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}, Converter={StaticResource bool2VisibilityConverter}}" />
                    </Grid>
                </Border>
                <ControlTemplate.Triggers>
                    <Trigger Property="WindowState" Value="Maximized">
                        <Setter TargetName="Maximize" Property="Visibility" Value="Collapsed" />
                        <Setter TargetName="Restore" Property="Visibility" Value="Visible" />
                        <Setter TargetName="LayoutRoot" Property="Margin" Value="7" />
                    </Trigger>
                    <Trigger Property="WindowState" Value="Normal">
                        <Setter TargetName="Maximize" Property="Visibility" Value="Visible" />
                        <Setter TargetName="Restore" Property="Visibility" Value="Collapsed" />
                    </Trigger>
                    <MultiTrigger>
                        <MultiTrigger.Conditions>
                            <Condition Property="ResizeMode" Value="CanResizeWithGrip" />
                            <Condition Property="WindowState" Value="Normal" />
                        </MultiTrigger.Conditions>
                        <Setter TargetName="ResizeGrip" Property="Visibility" Value="Visible" />
                    </MultiTrigger>
                </ControlTemplate.Triggers>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
    <Setter Property="WindowChrome.WindowChrome">
        <Setter.Value>
            <WindowChrome CornerRadius="0" GlassFrameThickness="1" UseAeroCaptionButtons="False" />
        </Setter.Value>
    </Setter>
</Style>

1
안녕하세요, 여러분이 게시 한이 훌륭한 코드에 대해 감사합니다. 부탁 하나만 부탁드립니다. 창문에 그림자를 드리울 수 있습니까? 내가 알아 낸 유일한 것은 변화 GlassFrameThickness1. 그러나 그림자가 너무 강하고 어둡습니다. 무게와 불투명도를 어떻게 변경할 수 있습니까?
xperator 2013 년


MahApps를 사용하는 대신 나만의 구성 요소 사용자 지정을 만드는 것이 매우 어렵습니까?
Matheus Saraiva

판타지 코! 이렇게 훌륭한 공헌을 해주셔서 대단히 감사합니다. 똑같은 일을 여러 번 시도했지만 이렇게 완벽한 결과를 얻지 못했습니다.
Leodev

상단에있는 파란색 테두리의 두께를 늘리고 다른 모든면의 테두리를 제거한다고 가정합니다 (예 : 답변의 elysium 그림). 무엇을 변경해야합니까? 나는 wpf를 처음 사용하므로 질문
mrid

49

내가 선택한 솔루션은 MahApps.Metro ( github ) 였는데 , (이제 두 개의 소프트웨어에서 사용한 후) 우수한 UI 키트를 고려합니다 ( 제안 을 위해 Oliver Vogel의 크레딧 ) .

창 스타일

매우 적은 노력으로 응용 프로그램을 스킨하고 표준 Windows 8 컨트롤을 수정했습니다. 매우 견고합니다.

텍스트 상자 워터 마크

Nuget에서 버전을 사용할 수 있습니다.

GUI (프로젝트를 마우스 오른쪽 버튼으로 클릭하고 Nuget 참조 관리, 'MahApps.Metro'검색)를 사용하거나 콘솔을 통해 Nuget을 통해 MahApps.Metro를 설치할 수 있습니다.

PM> 설치 패키지 MahApps.Metro

상업용으로 도 무료 입니다.

2013 년 10 월 29 일 업데이트 :

Github 버전의 MahApps.Metro에는 다음을 포함하여 현재 너겟 버전에서 사용할 수없는 컨트롤과 스타일이 포함되어 있음을 발견했습니다.

데이터 그리드 :

여기에 이미지 설명 입력

깨끗한 창 :

여기에 이미지 설명 입력

플라이 아웃 :

여기에 이미지 설명 입력

타일 ​​:

여기에 이미지 설명 입력

github 저장소는 많은 사용자 기여로 매우 활동적입니다. 나는 그것을 확인하는 것이 좋습니다.


나는 좋은 일 :) 테스트
Akrem

3
아주 좋은 업데이트! 또한 MahApps.Metro, Modern UI for WPF 및 Elysium을 사용해 봅니다. Elysium이 웹 사이트 / 문서에서 사용하기가 매우 복잡하고 혼동된다는 것을 알았습니다. Modern UI 및 MahApps.Metro는 가볍고 사용하기 쉽지만 MahApps입니다. Metro는 WPF 양식 컨트롤에서 더 경쟁력이 있습니다.

MahApps를 사용하는 대신 나만의 구성 요소 사용자 지정을 만드는 것이 매우 어렵습니까?
Matheus Saraiva

42

WPF 용 Modern UI를 권장 합니다.

매우 활동적인 메인테이너가 있습니다. 굉장하고 무료입니다!

WPF 용 최신 UI (샘플 애플리케이션 스크린 샷

저는 현재 일부 프로젝트를 MUI로 포팅하고 있습니다. 첫 번째 (그리고 두 번째) 인상은 정말 놀랍습니다!

작동중인 MUI를 보려면 MUI를 기반으로하는 XAML Spy 를 다운로드 할 수 있습니다.

편집 : WPF에 대한 최신 UI를 몇 달 동안 사용하고 있습니다.


16

위의 소스와 함께 Viktor La Croix 답변 을 기반으로 다음을 사용하도록 변경합니다.

Marlett 글꼴 예

최소화, 복원 / 최대화 및 닫기 버튼에 대해 경로 데이터 포인트보다 Marlett 글꼴을 사용하는 것이 더 좋습니다.

<StackPanel Orientation="Horizontal" HorizontalAlignment="Right" VerticalAlignment="Top" WindowChrome.IsHitTestVisibleInChrome="True" Grid.Row="0">
<Button Command="{Binding Source={x:Static SystemCommands.MinimizeWindowCommand}}" ToolTip="minimize" Style="{StaticResource WindowButtonStyle}">
    <Button.Content>
        <Grid Width="30" Height="25">
            <TextBlock Text="0" FontFamily="Marlett" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Center" Padding="3.5,0,0,3" />
        </Grid>
    </Button.Content>
</Button>
<Grid Margin="1,0,1,0">
    <Button x:Name="Restore" Command="{Binding Source={x:Static SystemCommands.RestoreWindowCommand}}" ToolTip="restore" Visibility="Collapsed" Style="{StaticResource WindowButtonStyle}">
        <Button.Content>
            <Grid Width="30" Height="25" UseLayoutRounding="True">
                <TextBlock Text="2" FontFamily="Marlett" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Center" Padding="2,0,0,1" />
            </Grid>
        </Button.Content>
    </Button>
    <Button x:Name="Maximize" Command="{Binding Source={x:Static SystemCommands.MaximizeWindowCommand}}" ToolTip="maximize" Style="{StaticResource WindowButtonStyle}">
        <Button.Content>
            <Grid Width="31" Height="25">
                <TextBlock Text="1" FontFamily="Marlett" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Center" Padding="2,0,0,1" />
            </Grid>
        </Button.Content>
    </Button>
</Grid>
<Button Command="{Binding Source={x:Static SystemCommands.CloseWindowCommand}}" ToolTip="close"  Style="{StaticResource WindowButtonStyle}">
    <Button.Content>
        <Grid Width="30" Height="25">
            <TextBlock Text="r" FontFamily="Marlett" FontSize="14" VerticalAlignment="Center" HorizontalAlignment="Center" Padding="0,0,0,1" />
        </Grid>
    </Button.Content>
</Button>


안녕하세요 플라잉 매버릭. marlett 글꼴을 사용하는 것이 더 좋은 방법을 설명 할 수 있습니까? 세 가지 구현이 있는데 어떤 구현을 사용해야할지 모르겠습니다. 첫 번째는 경로 데이터 포인트를 사용하고 두 번째는 marlett을 사용하고 세 번째는 SVG 형식의 버튼을 재현 한 것입니다. 이 프로젝트에서 100 % 모범 사례를 사용하려고하는데 어떤 것이 최선의 선택인지 확신 할 수 없습니다. Marlett이 더 나은 이유를 설명해 주시겠습니까?
user1632018 0:01에

1
안녕하세요 user1632018 Winform 또는 WPF에서 사용자 지정 크롬 창을 만들려면 시스템에서 사용할 수있는 'Marlett'글꼴을 살펴 봐야합니다. 이 글꼴에는 최소화, 최대화, 복원 및 닫기 버튼에 대해 Windows에서 사용되는 실제 글리프가 포함되어 있습니다. 이 글꼴을 사용하면 일반적으로 사용되는 사용자 지정 이미지 대신 사용자 지정 크롬 창에서 이러한 글리프를 정말 쉽게 재사용 할 수 있습니다. 자세한 내용은 Windows 문자표 또는 다음 링크에서 Marlett 글꼴을 살펴볼 수 있습니다. microsoft.com/typography/fonts/font.aspx?FMID=1264 도움이되기를 바랍니다.
FlyingMaverick 2014 년

2

지불 할 의향이 있다면 Telerik Components for WPF를 강력히 추천합니다 . 그들은 훌륭한 스타일 / 테마 를 제공하며 Office 2013 및 Windows 8 (편집 : 및 Visual Studio 2013 테마 스타일)에 대한 특정 테마가 있습니다. 그러나 실제로 스타일 이상의 것을 제공하면 실제로 유용한 컨트롤을 많이 얻을 수 있습니다.

작동 방식은 다음과 같습니다 (텔레 릭 샘플에서 가져온 스크린 샷) :

Telerik 대시 보드 샘플

Telerik CRM 대시 보드 샘플

다음은 telerik 경영진 대시 보드 샘플 (첫 번째 스크린 샷)과 CRM 대시 보드 (두 번째 스크린 샷)에 대한 링크입니다.

그들은 30 일 평가판을 제공합니다.


당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.