WPF-Anwendungen auch unter Windows 7 im Metro-Stil aussehen lassen? (Fenster Chrome / Theming / Theme)

123

Ich mag das Fensterchrom in der neuen Office Suite und in Visual Studio:

Geben Sie hier die Bildbeschreibung ein

Ich entwickle natürlich noch Anwendungen für Windows 7, aber ich frage mich, ob es eine schnelle und einfache Möglichkeit gibt (lesen Sie: WPF-Stil oder Windows-Bibliothek), diesen Stil zu emulieren. Ich habe in der Vergangenheit einige Fenster-Chrom-Stile verwendet, aber es ist wirklich schwierig, es so aussehen zu lassen, dass es genau richtig aussieht und sich richtig verhält.

Weiß jemand, ob Vorlagen oder Bibliotheken vorhanden sind, um meinen WPF-Anwendungen ein "Modern UI" -Look and Feel hinzuzufügen?

Daniel
quelle
8
Dieses Handbuch / NuGet-Paket kann hilfreich sein: MahaApps Metro Es enthält eine Reihe von Stilen und Steuerelementen zum Erstellen von WPF-Apps mit Metro-Look & Feel.
Oliver Vogel
Fragen, die uns bitten, ein Buch, ein Tool, eine Softwarebibliothek, ein Tutorial oder eine andere externe Ressource zu empfehlen oder zu finden, sind für Stack Overflow nicht thematisch, da sie dazu neigen, Meinungen und Spam zu finden. Beschreiben Sie stattdessen das Problem und die bisherigen Maßnahmen zur Lösung.
Scott Solmer

Antworten:

149

Ich habe mein eigenes Fenster und meinen eigenen Stil erstellt. Weil ich gerne die Kontrolle über alles habe und nicht wollte, dass einige externe Bibliotheken nur ein Fenster daraus verwenden. Ich habe mir bereits erwähnte MahApps.Metro auf GitHub angesehen

MahApps

und auch sehr schöne moderne Benutzeroberfläche auf GitHub . (Nur .NET4.5)

Moderne Benutzeroberfläche

Es gibt noch eine, es ist Elysium, aber ich habe diese wirklich nicht ausprobiert.

Elysium

Der Stil, den ich gemacht habe, war wirklich einfach, als ich sah, wie es in diesen gemacht wird. Jetzt habe ich mein eigenes Fenster und kann mit xaml machen, was ich will ... für mich ist es der Hauptgrund, warum ich mein eigenes gemacht habe. Und ich habe auch noch eine für dich gemacht :) Ich sollte wahrscheinlich sagen, dass ich es nicht schaffen würde, ohne die moderne Benutzeroberfläche zu erkunden. Es war eine große Hilfe. Ich habe versucht, es wie VS2012 Window aussehen zu lassen. Es sieht aus wie das.

Mein Fenster

Hier ist Code (bitte beachten Sie, dass er auf .NET4.5 abzielt)

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

Und hier Ressourcen:

<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>
Kapitán Mlíko
quelle
1
Hallo und vielen Dank für diesen großartigen Code, den Sie gepostet haben. Nur ein Gefallen zu fragen: Ist es möglich, einen Schatten auf dem Fenster zu haben? Das einzige , was ich herausgefunden verändert sich GlassFrameThicknesszu 1. Aber der Schatten ist zu stark und dunkel. Wie kann ich das Gewicht und die Deckkraft ändern?
Xperator
Ist es sehr schwierig, meine eigenen Anpassungen von Komponenten zu erstellen, anstatt MahApps zu verwenden?
Matheus Saraiva
Fantástico! Vielen Dank für diesen hervorragenden Beitrag. Ich hatte viele Male versucht, dasselbe zu tun, aber ich habe nie ein so perfektes Ergebnis erzielt.
Leodev
Angenommen, ich möchte die Dicke des blauen Randes oben erhöhen und den Rand an allen anderen Seiten entfernen (wie das Elysium-Bild in Ihrer Antwort). Was müsste ich ändern? Ich bin neu in wpf, und daher die Frage
mrid
49

Die Lösung, für die ich mich letztendlich entschieden habe, war MahApps.Metro ( Github ), das ich (nachdem ich es jetzt auf zwei Softwareteilen verwendet habe) als ausgezeichnetes UI-Kit betrachte ( Dank an Oliver Vogel für den Vorschlag) .

Fensterstil

Es häutet die Anwendung mit sehr geringem Aufwand und verfügt über Anpassungen der Standard-Windows 8-Steuerelemente. Es ist sehr robust.

Textfeld Wasserzeichen

Eine Version ist auf Nuget verfügbar:

Sie können MahApps.Metro über Nuget über die GUI (Rechtsklick auf Ihr Projekt, Verwalten von Nuget-Referenzen, Suche nach 'MahApps.Metro') oder über die Konsole installieren:

PM> Installationspaket MahApps.Metro

Es ist auch kostenlos - auch für den kommerziellen Gebrauch.

Update 29.10.2013:

Ich habe festgestellt, dass die Github-Version von MahApps.Metro zahlreiche Steuerelemente und Stile enthält, die in der aktuellen Nuget-Version nicht verfügbar sind, darunter:

Datagrids:

Geben Sie hier die Bildbeschreibung ein

Fenster reinigen:

Geben Sie hier die Bildbeschreibung ein

Flyouts:

Geben Sie hier die Bildbeschreibung ein

Fliesen:

Geben Sie hier die Bildbeschreibung ein

Das Github-Repository ist sehr aktiv und enthält einige Benutzerbeiträge. Ich empfehle es auszuprobieren.

Daniel
quelle
Ich
teste
3
sehr schönes Update! Ich versuche auch MahApps.Metro, Modern UI für WPF und Elysium. Ich fand, dass Elysium so kompliziert zu verwenden und auf ihrer Website / Doc zu verwirren ist. Modern UI und MahApps.Metro ist leicht und einfach zu bedienen, aber MahApps. Metro wettbewerbsfähiger bei WPF-Formularkontrollen.
Cheung
Ist es sehr schwierig, meine eigenen Anpassungen von Komponenten zu erstellen, anstatt MahApps zu verwenden?
Matheus Saraiva
42

Ich würde Modern UI für WPF empfehlen .

Es hat einen sehr aktiven Betreuer, es ist fantastisch und kostenlos!

Moderne Benutzeroberfläche für WPF (Screenshot der Beispielanwendung

Ich portiere derzeit einige Projekte auf MUI. Der erste (und mittlerweile zweite) Eindruck ist einfach nur Wow!

Um MUI in Aktion zu sehen, können Sie XAML Spy herunterladen, das auf MUI basiert.

EDIT: Verwenden Sie Modern UI für WPF ein paar Monate und ich liebe es!

Joel
quelle
16

Basierend auf der Antwort von Viktor La Croix mit der obigen Quelle würde ich sie ändern, um Folgendes zu verwenden:

Marlett-Schriftbeispiel

Es ist besser, die Marlett-Schriftart anstelle der Pfaddatenpunkte für die Schaltflächen Minimieren, Wiederherstellen / Maximieren und Schließen zu verwenden.

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

FlyingMaverick
quelle
Hallo fliegender Außenseiter. Könnten Sie erklären, warum es besser ist, die Marlett-Schriftart zu verwenden? Ich habe drei verschiedene Implementierungen und bin mir nicht sicher, welche ich verwenden soll. Der erste verwendet Pfaddatenpunkte, der zweite Marlett und der dritte eine Neuerstellung der Schaltflächen im SVG-Format. Ich versuche, in diesem Projekt 100% Best Practices zu verwenden, und bin mir nicht sicher, welche die beste Option ist. Können Sie erklären, warum Marlett besser ist?
user1632018
1
Hallo Benutzer1632018 Wenn Sie ein benutzerdefiniertes Chrome-Fenster in Winform oder WPF erstellen möchten, sollten Sie sich die auf Ihrem System verfügbare Schriftart 'Marlett' ansehen. Diese Schriftart enthält die tatsächlichen Glyphen, die in Windows für die Schaltflächen Minimieren, Maximieren, Wiederherstellen und Schließen verwendet werden. Die Verwendung dieser Schriftart macht es wirklich einfach, diese Glyphen in einem benutzerdefinierten Chromfenster wiederzuverwenden, anstatt benutzerdefinierte Bilder, die normalerweise verwendet werden. Weitere Informationen finden Sie in der Marlett-Schriftart in der Windows-Zeichentabelle oder unter folgendem Link: microsoft.com/typography/fonts/font.aspx?FMID=1264 Ich hoffe, dies hilft.
FlyingMaverick
2

Wenn Sie bereit sind zu zahlen, empfehle ich Ihnen dringend Telerik Components für WPF . Sie bieten großartige Stile / Themen und es gibt spezielle Themen für Office 2013 und Windows 8 (BEARBEITEN: sowie einen Visual Studio 2013-Themenstil). Wenn Sie jedoch viel mehr als nur Stile anbieten, erhalten Sie eine ganze Reihe von Steuerelementen, die wirklich nützlich sind.

So sieht es in Aktion aus (Screenshots aus Telerik-Beispielen):

Beispiel für ein Telerik-Dashboard

Beispiel für ein Telerik CRM-Dashboard

Hier sind die Links zum Beispiel des telerik Executive Dashboards (erster Screenshot) und hier zum CRM Dashboard (zweiter Screenshot).

Sie bieten eine 30-Tage-Testversion an, probieren Sie es einfach aus!

Joel
quelle
0

Schauen Sie sich dieses Fenster im WPF-Metro-Stil mit optionalen leuchtenden Rändern an .

Dies ist eine eigenständige Anwendung, die keine anderen Bibliotheken als Microsoft.Windows.Shell (im Lieferumfang enthalten) verwendet, um Fenster im Metro-Stil mit optionalen leuchtenden Rändern zu erstellen.

Unterstützt Windows bis zurück zu XP (.NET4).

Laila
quelle