0


开源C# WPF控件库:MahApps.Metro介绍

开源C# WPF控件库:MahApps.Metro 介绍

MahApps.Metro 项目仓库:Here

个人调试仓库:GitHub

根据仓库例子,采用Prism的MvvM框架手动coding过一遍:

1 下载相应Nuget包

<ProjectSdk="Microsoft.NET.Sdk"><PropertyGroup><OutputType>WinExe</OutputType><TargetFramework>net6.0-windows</TargetFramework><UseWPF>true</UseWPF></PropertyGroup><ItemGroup><PackageReferenceInclude="MahApps.Metro"Version="2.4.10"/><PackageReferenceInclude="MahApps.Metro.IconPacks"Version="4.11.0"/><PackageReferenceInclude="Prism.Unity"Version="8.1.97"/></ItemGroup></Project>

2 App.xaml

<prism:PrismApplication x:Class="PlayWithMahApps.MetroForWork.App"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:local="clr-namespace:PlayWithMahApps.MetroForWork"
             xmlns:prism="http://prismlibrary.com/" >
    <Application.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Themes/Light.Blue.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Application.Resources>
</prism:PrismApplication>
using Prism.Ioc;
using Prism.Regions;
using SelectNeidTool.Views;
using SelectNiedTool.Views;
using System.Windows;

namespace SelectNiedTool
{
    /// <summary>
    /// Interaction logic for App.xaml
    /// </summary>
    public partial class App
    {
        protected override Window CreateShell()
        {
            var window = Container.Resolve<MainWindow>();

            //window.Loaded += (sender, args) =>
            //{
            //    var manager = this.Container.Resolve<IRegionManager>();

            //    manager.RequestNavigate("ContentRegion", "DRWindows");
            //};

            return window;
        }

        protected override void RegisterTypes(IContainerRegistry containerRegistry)
        {
            containerRegistry.RegisterForNavigation<DRWindows>();
            containerRegistry.RegisterForNavigation<NRWindows>();

        }
    }
}

3 MainWindow.xaml

<mah:MetroWindow x:Class="PlayWithMahApps.MetroForWork.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
        xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks"                 
        xmlns:prism="http://prismlibrary.com/"
        prism:ViewModelLocator.AutoWireViewModel="True"
        xmlns:local="clr-namespace:SelectNeidTool.Views"
        Width="1024"
        Height="768"
        MinWidth="800"
        MinHeight="600" 
        Title="{Binding Title}">
    <Window.Resources>
        <ResourceDictionary>
            <Ellipse x:Key="AppThemeMenuIcon"
                     Width="16"
                     Height="16"
                     x:Shared="False"
                     Fill="{Binding ColorBrush, Mode=OneWay}"
                     Stroke="{Binding BorderColorBrush, Mode=OneWay}"
                     StrokeThickness="1" />
            <Ellipse x:Key="AccentMenuIcon"
                     Width="16"
                     Height="16"
                     x:Shared="False"
                     Fill="{Binding ColorBrush, Mode=OneWay}" />

            <Style x:Key="AppThemeMenuItemStyle"
                   BasedOn="{StaticResource MahApps.Styles.MenuItem}"
                   TargetType="{x:Type MenuItem}">
                <Setter Property="Command" Value="{Binding ChangeAccentCommand}" />
                <Setter Property="CommandParameter" Value="{Binding Name, Mode=OneWay}" />
                <Setter Property="Header" Value="{Binding Name, Mode=OneWay}" />
                <Setter Property="Icon" Value="{StaticResource AppThemeMenuIcon}" />
            </Style>

            <Style x:Key="AccentColorMenuItemStyle"
                   BasedOn="{StaticResource MahApps.Styles.MenuItem}"
                   TargetType="{x:Type MenuItem}">
                <Setter Property="Command" Value="{Binding ChangeAccentCommand}" />
                <Setter Property="CommandParameter" Value="{Binding Name, Mode=OneWay}" />
                <Setter Property="Header" Value="{Binding Name, Mode=OneWay}" />
                <Setter Property="Icon" Value="{StaticResource AccentMenuIcon}" />
            </Style>

            <!--  This is the template for the option menu item  -->
            <DataTemplate x:Key="HamburgerOptionsMenuItem" DataType="{x:Type mah:HamburgerMenuIconItem}">
                <DockPanel Height="48" LastChildFill="True">
                    <ContentControl x:Name="IconPart"
                                    Width="{Binding RelativeSource={RelativeSource AncestorType={x:Type mah:HamburgerMenu}}, Path=CompactPaneLength}"
                                    Content="{Binding Icon}"
                                    DockPanel.Dock="Left"
                                    Focusable="False"
                                    IsTabStop="False" />
                    <TextBlock x:Name="TextPart"
                               VerticalAlignment="Center"
                               FontSize="16"
                               Text="{Binding Label}" />
                </DockPanel>
                <DataTemplate.Triggers>
                    <DataTrigger Binding="{Binding RelativeSource={RelativeSource AncestorType={x:Type mah:HamburgerMenu}}, Path=PanePlacement}" Value="Right">
                        <Setter TargetName="IconPart" Property="DockPanel.Dock" Value="Right" />
                        <Setter TargetName="TextPart" Property="Margin" Value="8 0 0 0" />
                    </DataTrigger>
                </DataTemplate.Triggers>
            </DataTemplate>

        </ResourceDictionary>
    </Window.Resources>

    <!--How to set window icon from iconpack-->
    <!--use the IconTemplate property to set a custom Icon at the title bar.-->
    <!--https://github.com/MahApps/MahApps.Metro/issues/3464-->
    <mah:MetroWindow.IconTemplate>
        <DataTemplate>
            <iconPacks:PackIconMaterial Width="{TemplateBinding Width}"
                                      Height="{TemplateBinding Height}"
                                      Margin="4"
                                      Foreground="{DynamicResource IdealForegroundColorBrush}"
                                      Kind="TransmissionTower" />
        </DataTemplate>
    </mah:MetroWindow.IconTemplate>

    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="*" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <Menu Grid.Row="0"
              Margin="5"
              HorizontalAlignment="Left"
              VerticalAlignment="Stretch">
            <MenuItem Header="Theme"
                      ItemContainerStyle="{StaticResource AppThemeMenuItemStyle}"
                      ItemsSource="{Binding AppThemes, Mode=OneWay}" />
            <MenuItem Header="Accent"
                      ItemContainerStyle="{StaticResource AccentColorMenuItemStyle}"
                      ItemsSource="{Binding AccentColors, Mode=OneWay}" />
        </Menu>

        <Border Grid.Row="1"
                BorderBrush="{DynamicResource MahApps.Brushes.Gray7}"
                BorderThickness="1">

            <mah:HamburgerMenu x:Name="HamburgerMenuControl"
                               DisplayMode="CompactOverlay"
                               HamburgerWidth="48"
                               IsPaneOpen="{Binding IsHamburgerMenuPaneOpen}"
                               ItemTemplate="{StaticResource HamburgerOptionsMenuItem}"
                               SelectedIndex="0"
                               VerticalScrollBarOnLeftSide="False">

                <!--  Items  -->
                <mah:HamburgerMenu.ItemsSource>
                    <mah:HamburgerMenuItemCollection>
                        <mah:HamburgerMenuIconItem x:Name="AboutOption"
                                                   Command="{Binding DRCommand}"
                                                   Label="LTE_DRAN">
                            <mah:HamburgerMenuIconItem.Icon>
                                <iconPacks:PackIconMaterial Width="22"
                                                            Height="22"
                                                            HorizontalAlignment="Center"
                                                            VerticalAlignment="Center"
                                                            Kind="Signal4g" />
                            </mah:HamburgerMenuIconItem.Icon>
                        </mah:HamburgerMenuIconItem>

                        <mah:HamburgerMenuIconItem x:Name="AboutOption2"
                                                   Command="{Binding NRCommand}"
                                                   Label="NR">
                            <mah:HamburgerMenuIconItem.Icon>
                                <!--  iconPacks need to be downloaded through Nuget, and icon by kind property-->
                                <iconPacks:PackIconMaterial Width="22"
                                                            Height="22"
                                                            HorizontalAlignment="Center"
                                                            VerticalAlignment="Center"
                                                            Kind="Signal5g" />
                            </mah:HamburgerMenuIconItem.Icon>
                        </mah:HamburgerMenuIconItem>

                        <mah:HamburgerMenuIconItem x:Name="AboutOption3"
                                                   Command="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=mah:HamburgerMenu}, Path=DataContext.ShowHamburgerAboutCommand}"
                                                   Label="ToolBox">
                            <mah:HamburgerMenuIconItem.Icon>
                                <iconPacks:PackIconMaterial Width="22"
                                                            Height="22"
                                                            HorizontalAlignment="Center"
                                                            VerticalAlignment="Center"
                                                            Kind="Tools"/>
                            </mah:HamburgerMenuIconItem.Icon>
                        </mah:HamburgerMenuIconItem>

                    </mah:HamburgerMenuItemCollection>
                </mah:HamburgerMenu.ItemsSource>

                <!--Refer to https://elf-mission.net/programming/wpf/ui-gallery/case01-01/-->
                <!--Refer to https://yutampo-blog.com/12-opencv%E3%81%A7%E7%94%BB%E5%83%8F%E5%87%A6%E7%90%86%E3%82%A2%E3%83%97%E3%83%AA%E3%82%92%E4%BD%9C%E3%82%8D%E3%81%86hambergermenu2/-->
                <mah:HamburgerMenu.Content>
                    <mah:TransitioningContentControl x:Name="ContentRegion"
                                                   prism:RegionManager.RegionName="ContentRegion"
                                                   Transition="RightReplace"/>
                </mah:HamburgerMenu.Content>
            </mah:HamburgerMenu>
        </Border>
    </Grid>
</mah:MetroWindow>                 

MainWindow.xaml.cs

using System.Windows;
using MahApps.Metro.Controls;
using Prism.Regions;

namespace SelectNiedTool.Views
{
    /// <summary>
    /// Interaction logic for MainWindow.xaml
    /// </summary>
    public partial class MainWindow : MetroWindow
    {
        public MainWindow()
        {
            InitializeComponent();

            /* HamburgerMenu.Content 上に配置したコントロールは遅延作成されるらしく、
             * Prism の RegionManager は遅延作成された Region を認識できないため RequestNavigate が認識されない
             * これを回避するには Region を手動で RegionManager に登録する必要があるようなので、MainWindow のコードビハインドに 上記の処理を追加します。*/
            RegionManager.SetRegionName(this.ContentRegion, "ContentRegion");

            var regionMan = (IRegionManager)Prism.Ioc.ContainerLocator.Container.Resolve(typeof(IRegionManager));
            RegionManager.SetRegionManager(ContentRegion, regionMan);

        }

        private void HamburgerMenuControl_OnItemInvoked(object sender, HamburgerMenuItemInvokedEventArgs e)
        {
            this.HamburgerMenuControl.Content = e.InvokedItem;

            if (!e.IsItemOptions && this.HamburgerMenuControl.IsPaneOpen)
            {
                // close the menu if a item was selected
                this.HamburgerMenuControl.IsPaneOpen = false;
            }
        }
    }
}

4 DRWindows.xaml

<UserControl x:Class="PlayWithMahApps.MetroForWork.Views.DRWindows"
             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:SelectNeidTool.Views"
             xmlns:mah="http://metro.mahapps.com/winfx/xaml/controls"
             xmlns:iconPacks="http://metro.mahapps.com/winfx/xaml/iconpacks" 
             mc:Ignorable="d" 
             d:DesignHeight="600" d:DesignWidth="800">

    <UserControl.Resources>
        <Thickness x:Key="ControlMargin">5 5 5 5</Thickness>
    </UserControl.Resources>

    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>
        <Grid.RowDefinitions>
            <RowDefinition />
            <RowDefinition />
            <RowDefinition />
        </Grid.RowDefinitions>

        <StackPanel Grid.Column="0">
            <mah:MetroHeader Header="{Binding InputTitle}" Margin="{StaticResource ControlMargin}">
                <TextBox  Text="{Binding InputPath, Mode=TwoWay}" />
            </mah:MetroHeader>
            
            <Button Width="110"
                    Margin="{StaticResource ControlMargin}"
                    Content="Diagnose"
                    Command="{Binding DiagnoseCommand}"
                    Style="{DynamicResource MahApps.Styles.Button.Square}" />

            <Button Width="110"
                    Margin="{StaticResource ControlMargin}"
                    Content="Check"
                    Style="{DynamicResource MahApps.Styles.Button.Square.Highlight}" />

            <Button Width="110"
                    Margin="{StaticResource ControlMargin}"
                    Content="Test"
                    Style="{DynamicResource MahApps.Styles.Button.Square.Highlight}" />
        </StackPanel>

        <StackPanel Grid.Row="0"
                    Grid.Column="1"
                    HorizontalAlignment="Center"
                    UseLayoutRounding="True">
            <StackPanel>
                <StackPanel.Resources>
                    <Style BasedOn="{StaticResource MahApps.Styles.CheckBox.Win10}" TargetType="{x:Type CheckBox}">
                        <Setter Property="ContentTemplate">
                            <Setter.Value>
                                <DataTemplate>
                                    <TextBlock Text="{Binding RelativeSource={RelativeSource AncestorType={x:Type CheckBox}}, Path=IsChecked, TargetNullValue='IsChecked = Null', Mode=OneWay, StringFormat='{}IsChecked = {0}'}" />
                                </DataTemplate>
                            </Setter.Value>
                        </Setter>
                        <Setter Property="Margin" Value="{StaticResource ControlMargin}" />
                    </Style>
                </StackPanel.Resources>

                <Label Content="Select BandWidth" Style="{DynamicResource DescriptionHeaderStyle}" />
                <CheckBox mah:CheckBoxHelper.CheckCornerRadius="2"
                          IsChecked="False"
                          IsEnabled="True" />
                <CheckBox mah:CheckBoxHelper.CheckCornerRadius="2"
                          IsChecked="False"
                          IsEnabled="True" />
                <CheckBox mah:CheckBoxHelper.CheckCornerRadius="2"
                          IsChecked="False"
                          IsEnabled="True" />
                <CheckBox mah:CheckBoxHelper.CheckCornerRadius="2"
                          IsChecked="False"
                          IsEnabled="True" />
                <CheckBox mah:CheckBoxHelper.CheckCornerRadius="2"
                          IsChecked="False"
                          IsEnabled="True" />
            </StackPanel>

        </StackPanel>

        <RichTextBox Grid.Row="0"
                     Grid.RowSpan="3"
                     Grid.Column="2"
                     Grid.ColumnSpan="3"
                     Margin="{StaticResource ControlMargin}"
                     mah:TextBoxHelper.SelectAllOnFocus="True"
                     IsDocumentEnabled="True"
                     SpellCheck.IsEnabled="True">
            <FlowDocument>
                <Paragraph>
                    <Run>Log Begin</Run>
                    <LineBreak />
                    <Run Text="{Binding Log}" />
                    <LineBreak />
                    <Run>Log Over</Run>
                </Paragraph>
            </FlowDocument>
        </RichTextBox>

    </Grid>
</UserControl>   

5 MainWindowViewModel.cs

using ControlzEx.Theming;
using Prism.Commands;
using Prism.Mvvm;
using Prism.Regions;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Media;

namespace PlayWithMahApps.ViewModels
{
    public class MainWindowViewModel : BindableBase
    {
        private string _title = "Prism Application";
        public string Title
        {
            get { return _title; }
            set { SetProperty(ref _title, value); }
        }

        public List<AppThemeMenuData> AppThemes { get; set; }

        public List<AccentColorMenuData> AccentColors { get; set; }

        public MainWindowViewModel(IRegionManager regionManager)
        {
            // create metro theme color menu items for the demo
            this.AppThemes = ThemeManager.Current.Themes
                                         .GroupBy(x => x.BaseColorScheme)
                                         .Select(x => x.First())
                                         .Select(a => new AppThemeMenuData { Name = a.BaseColorScheme, BorderColorBrush = a.Resources["MahApps.Brushes.ThemeForeground"] as Brush, ColorBrush = a.Resources["MahApps.Brushes.ThemeBackground"] as Brush })
                                         .ToList();

            // create accent color menu items for the demo
            this.AccentColors = ThemeManager.Current.Themes
                                            .GroupBy(x => x.ColorScheme)
                                            .OrderBy(a => a.Key)
                                            .Select(a => new AccentColorMenuData { Name = a.Key, ColorBrush = a.First().ShowcaseBrush })
                                            .ToList();

            this._regionManager = regionManager;

            DRCommand = new DelegateCommand(DRNavigation);
            NRCommand = new DelegateCommand(NRNavigation);

            //Initialize the default region view
            //Refer to https://stackoverflow.com/questions/54330435/navigate-to-a-default-view-when-application-loaded-using-prism-7-in-wpf
            regionManager.RegisterViewWithRegion("ContentRegion", "DRWindows");

        }

        private DelegateCommand _fieldName;
        public DelegateCommand CommandName =>
            _fieldName ?? (_fieldName = new DelegateCommand(ExecuteCommandName));

        void ExecuteCommandName()
        {
            return;
        }

        #region Region Navigation

        //XAML中定义了RegionManager,ViewModel里可以接收这个RegionManager
        //RegionManager顾名思义,管理Region
        private readonly IRegionManager _regionManager;

        public DelegateCommand DRCommand { get; private set; }
        public DelegateCommand NRCommand { get; private set; }

        void DRNavigation()
        {
            if (_regionManager != null)
            {
                //注意,方法与Region注册不同,是Navigate关联的方法
                _regionManager.RequestNavigate("ContentRegion", "DRWindows");
            }
        }

        void NRNavigation()
        {
            if (_regionManager != null)
            {
                _regionManager.RequestNavigate("ContentRegion", "NRWindows");
            }
        }

        #endregion

    }

    public class AppThemeMenuData : AccentColorMenuData
    {
        protected override void DoChangeTheme(string? name)
        {
            if (name is not null)
            {
                ThemeManager.Current.ChangeThemeBaseColor(Application.Current, name);
            }
        }
    }

    public class AccentColorMenuData
    {
        public string? Name { get; set; }

        public Brush? BorderColorBrush { get; set; }

        public Brush? ColorBrush { get; set; }

        public AccentColorMenuData()
        {
            //Update SimpleCommand with DelegateCommand 
            // this.ChangeAccentCommand = new SimpleCommand<string?>(o => true, this.DoChangeTheme);
            this.ChangeAccentCommand = new DelegateCommand<string>(ExecuteChangeACommand, CanExecuteChangeACommand);
        }

        void ExecuteChangeACommand(string name)
        {
            this.DoChangeTheme(name);
        }

        bool CanExecuteChangeACommand(string name)
        {
            return true;
        }

        public ICommand ChangeAccentCommand { get; }

        protected virtual void DoChangeTheme(string? name)
        {
            if (name is not null)
            {
                ThemeManager.Current.ChangeThemeColorScheme(Application.Current, name);
            }
        }

    }
}

6 DRWindowsViewModel.cs

using Microsoft.WindowsAPICodePack.Dialogs;
using Prism.Commands;
using Prism.Mvvm;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace PlayWithMahApps.ViewModels
{
    class DRWindowsViewModel : BindableBase
    {

        /// <summary>
        /// Property for log
        /// </summary>
        private string _log = @"";
        public string Log
        {
            get { return _log; }
            set { SetProperty(ref _log, value + Environment.NewLine); }
        }

        /// <summary>
        /// Input file Label
        /// </summary>
        private string _inputTitle = "File Path";
        public string InputTitle
        {
            get { return _inputTitle; }
            set { SetProperty(ref _inputTitle, value); }
        }

        /// <summary>
        /// Input file path
        /// </summary>
        private string _inputPath = "Please input file";
        public string InputPath
        {
            get { return _inputPath; }
            set { SetProperty(ref _inputPath, value); }
        }

        /// <summary>
        /// Select file path and Diagnose
        /// </summary>
        private DelegateCommand _diagnose;
        public DelegateCommand DiagnoseCommand =>
            _diagnose ?? (_diagnose = new DelegateCommand(ExecuteDiagnoseCommand));

        void ExecuteDiagnoseCommand()
        {
            //Please install WindowsAPICodePack-Shell in Nuget
            using (var cofd = new CommonOpenFileDialog()
            {
                Title = "Please Select  File",
                InitialDirectory = @"C:",
                IsFolderPicker = true,
            })
            {
                if (cofd.ShowDialog() != CommonFileDialogResult.Ok)
                {
                    return;
                }

                this.InputPath = cofd.FileName;

                System.Windows.MessageBox.Show($"{cofd.FileName} is Selected");
            }

            for(int i = 0; i < 2000; i++)
            {
                Log += $"Test: {i}";
            }

        }

    }
}
标签: 开源 c# wpf

本文转载自: https://blog.csdn.net/watershed1993/article/details/134967223
版权归原作者 watershed1993 所有, 如有侵权,请联系我们删除。

“开源C# WPF控件库:MahApps.Metro介绍”的评论:

还没有评论