WPF uygulamalarının Windows 7'de bile Metro tarzı görünmesini sağlamak mı? (Pencere Kromu / Tema / Tema)


123

Yeni Office Paketi ve Visual Studio'daki pencere kromunu beğendim:

görüntü açıklamasını buraya girin

Elbette hala Windows 7 için uygulamalar geliştiriyorum, ancak bu stili taklit etmenin hızlı ve kolay bir yolu (okuyun: WPF stili veya Windows Kitaplığı) olup olmadığını merak ediyorum. Geçmişte bazı pencere krom stillerini yaptım, ancak doğru görünmesini ve doğru davranmasını sağlamak gerçekten zor.

WPF uygulamalarıma "Modern UI" görünümü ve hissi eklemek için mevcut şablonlar veya kitaplıklar olup olmadığını bilen var mı?


8
Bu Kılavuz / NuGet Paketi yardımcı olabilir: MahaApps Metro Metro Görünümü ve hissi ile WPF Uygulamaları oluşturmak için bir dizi stil ve kontrol içerir.
Oliver Vogel

Bir kitap, araç, yazılım kitaplığı, öğretici veya diğer site dışı kaynakları önermemizi veya bulmamızı isteyen sorular, uygun yanıtları ve spam'leri çekme eğiliminde olduklarından Stack Overflow için konu dışıdır. Bunun yerine, sorunu ve çözmek için şimdiye kadar neler yapıldığını açıklayın.
Scott Solmer

Yanıtlar:


149

Yaptığım şey kendi Penceremi ve Tarzımı yaratmaktı. Çünkü her şey üzerinde kontrole sahip olmaktan hoşlanıyorum ve bazı harici kitaplıkların ondan bir Pencere kullanmasını istemedim. GitHub'da daha önce bahsedilen MahApps.Metro'ya baktım

MahApps

ve ayrıca GitHub'da çok güzel Modern UI . (Yalnızca .NET4.5)

Modern kullanıcı arayüzü

Elysium olan bir tane daha var ama bunu gerçekten denemedim.

cennet

Bunlarla nasıl yapıldığına baktığımda yaptığım tarz gerçekten çok kolaydı. Şimdi kendi Pencerem var ve xaml ile istediğimi yapabilirim ... benim için kendi penceremi yapmamın ana nedeni bu. Ve sizin için de bir tane daha yaptım :) Muhtemelen Modern UI'yi keşfetmeden bunu yapamayacağımı söylemeliyim, bu çok yardımcı oldu. VS2012 Penceresi gibi görünmesini sağlamaya çalıştım. Şuna benziyor.

Benim pencerem

İşte kod (bunun .NET4.5'i hedeflediğini lütfen unutmayın)

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);
    }
}

Ve burada kaynaklar:

<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
Merhaba ve gönderdiğiniz bu harika kod için çok teşekkür ederim. Sadece sormak için bir iyilik, Pencerede gölge olması mümkün mü? Ben anladım tek şey değişiyor GlassFrameThicknessiçin 1. Ama gölge çok güçlü ve karanlık. Ağırlığını ve opaklığını nasıl değiştirebilirim?
xperator


MahApps kullanmak yerine kendi bileşenlerimi özelleştirmem çok mu zor?
Matheus Saraiva

Fantástico! Bu mükemmel katkı için çok teşekkür ederim, aynı şeyi defalarca yapmaya çalıştım ama hiç bu kadar mükemmel bir sonuç almadım.
Leodev

Üstteki mavi kenarlığın kalınlığını artırmak ve diğer tüm kenarları kaldırmak (cevabınızdaki elysium pic gibi) istediğimi varsayalım, neyi değiştirmeliyim?
Wpf'de yeniyim

49

Seçtiğim çözüm MahApps.Metro'ydu ( github ), ki bu (şimdi iki yazılım parçası üzerinde kullandıktan sonra) mükemmel bir UI kiti olarak düşünüyorum ( öneri için Oliver Vogel'e teşekkür ediyorum ) .

Pencere stili

Çok az çabayla uygulamayı kaplar ve standart Windows 8 kontrollerinin uyarlamalarına sahiptir. Çok sağlam.

Metin kutusu filigranı

Nuget'te bir sürüm mevcuttur:

GUI (projenize sağ tıklayın, Nuget Referanslarını Yönet, 'MahApps.Metro' arayın) veya konsol aracılığıyla Nuget aracılığıyla MahApps.Metro'yu kurabilirsiniz:

PM> Kurulum Paketi MahApps.Metro

Ayrıca ücretsizdir - ticari kullanım için bile.

10-29-2013 Güncellemesi:

MahApps.Metro'nun Github sürümünün şu anki nuget sürümünde bulunmayan kontroller ve stillerle dolu olduğunu keşfettim:

datagrids:

görüntü açıklamasını buraya girin

Temiz Pencere:

görüntü açıklamasını buraya girin

açılır pencereler:

görüntü açıklamasını buraya girin

Fayans:

görüntü açıklamasını buraya girin

Github deposu, oldukça fazla kullanıcı katkısı ile oldukça aktif. şuna bir bakmanı öneririm.


Test ediyorum güzel +1 :)
Akrem

3
çok güzel güncelleme! Ayrıca MahApps.Metro, WPF ve Elysium için Modern UI'yi de deniyorum.Elysium'un web sitesinde / Doc'ta kullanımı çok karmaşık ve kafa karıştırıcı buldum .. Modern UI ve MahApps.Metro hafif ve kullanımı kolay, ancak MahApps. WPF form kontrollerinde daha rekabetçi Metro.
Cheung

MahApps kullanmak yerine kendi bileşen özelleştirmelerimi yaratmak çok mu zor?
Matheus Saraiva

42

WPF için Modern UI tavsiye ederim .

Çok aktif bir bakıcısı var, harika ve ücretsiz!

WPF için Modern UI (Örnek uygulamanın ekran görüntüsü

Şu anda bazı projeleri MUI'ye aktarıyorum, ilk (ve bu arada ikinci) izlenim sadece vay!

MUI'yi çalışırken görmek için MUI'ye dayanan XAML Spy'ı indirebilirsiniz .

DÜZENLEME: WPF için Modern Kullanıcı Arayüzünü birkaç ay kullanmak ve onu seviyorum!


16

Yukarıdaki kaynakla Viktor La Croix cevabına dayanarak , aşağıdakileri kullanmak için değiştirirdim:

Marlett Yazı Tipi Örneği

Küçült, Geri Yükle / Büyüt ve Kapat düğmeleri için Yol Verisi noktaları yerine Marlett yazı tipini kullanmak daha iyi bir uygulamadır.

<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>


Merhaba Flying maverick. Marlett yazı tipini kullanmanın neden daha iyi bir uygulama olduğunu açıklayabilir misiniz? Üç farklı uygulamam var ve hangisini kullanacağımdan emin değilim. Birincisi yol veri noktalarını kullanıyor, ikincisi marlett kullanıyor ve üçüncüsü düğmelerin SVG formatında yeniden oluşturulması. Bu projede% 100 en iyi uygulamaları kullanmaya çalışıyorum ve hangisinin en iyi seçenek olduğundan emin değilim. Marlett'in neden daha iyi olduğunu açıklayabilir misiniz?
user1632018

1
Merhaba kullanıcı1632018 Winform veya WPF'de özel bir krom pencere oluşturmak istiyorsanız, sisteminizde bulunan 'Marlett' yazı tipine bir göz atmalısınız. Bu yazı tipi, Windows'ta Simge Durumuna Küçült, Büyüt, Geri Yükle ve Kapat düğmeleri için kullanılan gerçek glifleri içerir. Bu yazı tipini kullanmak, bu glifleri tipik olarak kullanılan özel görüntüler yerine özel bir krom penceresinde yeniden kullanmayı gerçekten kolaylaştırır. Daha fazla ayrıntı için Windows Karakter Haritası'ndaki Marlett yazı tipine veya aşağıdaki bağlantıya bakabilirsiniz: microsoft.com/typography/fonts/font.aspx?FMID=1264 Bunun yardımcı olacağını umuyoruz.
FlyingMaverick

2

Ödemeye razı iseniz, WPF için Telerik Bileşenlerini şiddetle tavsiye ederim . Harika stiller / temalar sunarlar ve hem Office 2013 hem de Windows 8 için özel temalar vardır (DÜZENLEME: ve ayrıca bir Visual Studio 2013 temalı stil). Bununla birlikte, orada stillerden çok daha fazlasını sunan, aslında gerçekten kullanışlı olan bir sürü kontrol alacaksınız.

İşte iş başında nasıl göründüğü (telerik örneklerinden alınan ekran görüntüleri):

Telerik Dashboard Örneği

Telerik CRM Dashboard Örneği

İşte telerik yönetici gösterge panosu örneğinin bağlantıları (ilk ekran görüntüsü) ve CRM Dashboard (ikinci ekran görüntüsü) için burada.

30 günlük bir deneme sunuyorlar, sadece bir şans verin!


Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.