引入自定义窗口
This commit is contained in:
		
							
								
								
									
										61
									
								
								DeedyDesigner/Deedy.Testing/ElegantWindow.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										61
									
								
								DeedyDesigner/Deedy.Testing/ElegantWindow.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,61 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using System.Windows;
 | 
			
		||||
using System.Windows.Controls;
 | 
			
		||||
using System.Windows.Data;
 | 
			
		||||
using System.Windows.Documents;
 | 
			
		||||
using System.Windows.Input;
 | 
			
		||||
using System.Windows.Media;
 | 
			
		||||
using System.Windows.Media.Imaging;
 | 
			
		||||
using System.Windows.Navigation;
 | 
			
		||||
using System.Windows.Shapes;
 | 
			
		||||
 | 
			
		||||
namespace Deedy.Testing
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
 | 
			
		||||
    ///
 | 
			
		||||
    /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
 | 
			
		||||
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
 | 
			
		||||
    /// 元素中:
 | 
			
		||||
    ///
 | 
			
		||||
    ///     xmlns:MyNamespace="clr-namespace:Deedy.Testing"
 | 
			
		||||
    ///
 | 
			
		||||
    ///
 | 
			
		||||
    /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
 | 
			
		||||
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
 | 
			
		||||
    /// 元素中:
 | 
			
		||||
    ///
 | 
			
		||||
    ///     xmlns:MyNamespace="clr-namespace:Deedy.Testing;assembly=Deedy.Testing"
 | 
			
		||||
    ///
 | 
			
		||||
    /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
 | 
			
		||||
    /// 并重新生成以避免编译错误:
 | 
			
		||||
    ///
 | 
			
		||||
    ///     在解决方案资源管理器中右击目标项目,然后依次单击
 | 
			
		||||
    ///     “添加引用”->“项目”->[浏览查找并选择此项目]
 | 
			
		||||
    ///
 | 
			
		||||
    ///
 | 
			
		||||
    /// 步骤 2)
 | 
			
		||||
    /// 继续操作并在 XAML 文件中使用控件。
 | 
			
		||||
    ///
 | 
			
		||||
    ///     <MyNamespace:ElegantWindow/>
 | 
			
		||||
    ///
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public class ElegantWindow : Window
 | 
			
		||||
    {
 | 
			
		||||
        static ElegantWindow()
 | 
			
		||||
        {
 | 
			
		||||
            DefaultStyleKeyProperty.OverrideMetadata(typeof(ElegantWindow), new FrameworkPropertyMetadata(typeof(ElegantWindow)));
 | 
			
		||||
        }
 | 
			
		||||
        public ElegantWindow() : base()
 | 
			
		||||
        {
 | 
			
		||||
        }
 | 
			
		||||
        public override void OnApplyTemplate()
 | 
			
		||||
        {
 | 
			
		||||
            base.OnApplyTemplate();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										86
									
								
								DeedyDesigner/Deedy.Testing/ExMarkup.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										86
									
								
								DeedyDesigner/Deedy.Testing/ExMarkup.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,86 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.ComponentModel;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using System.Windows;
 | 
			
		||||
using System.Windows.Controls;
 | 
			
		||||
 | 
			
		||||
namespace Deedy
 | 
			
		||||
{
 | 
			
		||||
    public class ExMarkup : DependencyObject
 | 
			
		||||
    {
 | 
			
		||||
 | 
			
		||||
        public static WindowDecorator GetWindowChrome(DependencyObject obj)
 | 
			
		||||
        {
 | 
			
		||||
            return (WindowDecorator)obj.GetValue(WindowChromeProperty);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetWindowChrome(DependencyObject obj, WindowDecorator value)
 | 
			
		||||
        {
 | 
			
		||||
            obj.SetValue(WindowChromeProperty, value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // 用于自定义窗体的标题栏
 | 
			
		||||
        public static readonly DependencyProperty WindowChromeProperty =
 | 
			
		||||
            DependencyProperty.RegisterAttached("WindowChrome", typeof(WindowDecorator), typeof(ExMarkup), new PropertyMetadata(null, (d, e) =>
 | 
			
		||||
            {
 | 
			
		||||
                if (e.NewValue == null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (e.OldValue != null) ((WindowDecorator)e.OldValue).OnDetaching();
 | 
			
		||||
                }
 | 
			
		||||
                else
 | 
			
		||||
                {
 | 
			
		||||
                    if (d is Decorator)
 | 
			
		||||
                    {
 | 
			
		||||
                        Decorator header = (Decorator)d;
 | 
			
		||||
                        FrameworkElement? parent = header.Parent as FrameworkElement;
 | 
			
		||||
                        Window? target = parent as Window;
 | 
			
		||||
                        while (parent != null && target == null)
 | 
			
		||||
                        {
 | 
			
		||||
                            parent = parent.Parent as FrameworkElement;
 | 
			
		||||
                            target = parent as Window;
 | 
			
		||||
                        }
 | 
			
		||||
 | 
			
		||||
                        if (target != null) ((WindowDecorator)e.NewValue).OnAttached(target, header);
 | 
			
		||||
                        else
 | 
			
		||||
                        {
 | 
			
		||||
                            if (!DesignerProperties.GetIsInDesignMode(d))
 | 
			
		||||
                                throw new InvalidOperationException("窗体装饰器[WindowDecorator]对象在附加到作为标题栏容器的[Decorator]类型派生对象(例如[Border]对象)前,该容器必须已经挂接到一个窗体对象的视觉树上!");
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                    else throw new InvalidOperationException("窗体装饰器[WindowDecorator]对象只能附加到作为标题栏容器的[Decorator]类型派生对象(例如[Border]对象)上!");
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public static string GetTextBoxRegexMatch(DependencyObject obj)
 | 
			
		||||
        {
 | 
			
		||||
            return (string)obj.GetValue(TextBoxRegexMatchProperty);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static void SetTextBoxRegexMatch(DependencyObject obj, string value)
 | 
			
		||||
        {
 | 
			
		||||
            obj.SetValue(TextBoxRegexMatchProperty, value);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Using a DependencyProperty as the backing store for TextBoxRegexMatch.  This enables animation, styling, binding, etc...
 | 
			
		||||
        public static readonly DependencyProperty TextBoxRegexMatchProperty =
 | 
			
		||||
            DependencyProperty.RegisterAttached("TextBoxRegexMatch", typeof(string), typeof(ExMarkup), new PropertyMetadata("", (d, e) =>
 | 
			
		||||
            {
 | 
			
		||||
                if (d is TextBox textBox)
 | 
			
		||||
                {
 | 
			
		||||
                    if (!string.IsNullOrEmpty(e.NewValue as string) && string.IsNullOrEmpty(e.OldValue as string))
 | 
			
		||||
                    {
 | 
			
		||||
                        //加事件监听逻辑
 | 
			
		||||
                    }
 | 
			
		||||
                    if (string.IsNullOrEmpty(e.NewValue as string) && !string.IsNullOrEmpty(e.OldValue as string))
 | 
			
		||||
                    {
 | 
			
		||||
                        //取消事件监听逻辑
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										83
									
								
								DeedyDesigner/Deedy.Testing/Themes/Generic.xaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										83
									
								
								DeedyDesigner/Deedy.Testing/Themes/Generic.xaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,83 @@
 | 
			
		||||
<ResourceDictionary
 | 
			
		||||
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 | 
			
		||||
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 | 
			
		||||
    xmlns:local="clr-namespace:Deedy.Testing"
 | 
			
		||||
    xmlns:deedy="clr-namespace:Deedy">
 | 
			
		||||
 | 
			
		||||
    <Style TargetType="{x:Type deedy:WindowDecorator}">
 | 
			
		||||
        <Setter Property="HorizontalContentAlignment" Value="Left"/>
 | 
			
		||||
        <Setter Property="HoverBrush" Value="Silver"/>
 | 
			
		||||
        <Setter Property="Padding" Value="6"/>
 | 
			
		||||
        <Setter Property="Template">
 | 
			
		||||
            <Setter.Value>
 | 
			
		||||
                <ControlTemplate TargetType="{x:Type deedy:WindowDecorator}">
 | 
			
		||||
                    <ControlTemplate.Resources>
 | 
			
		||||
                        <Style x:Key="controlButtonStyle" TargetType="{x:Type Button}">
 | 
			
		||||
                            <Setter Property="Background" Value="Transparent"/>
 | 
			
		||||
                            <Setter Property="Template">
 | 
			
		||||
                                <Setter.Value>
 | 
			
		||||
                                    <ControlTemplate TargetType="{x:Type Button}">
 | 
			
		||||
                                        <Border Background="{TemplateBinding Background}">
 | 
			
		||||
                                            <ContentPresenter Margin="{TemplateBinding Padding}"/>
 | 
			
		||||
                                        </Border>
 | 
			
		||||
                                    </ControlTemplate>
 | 
			
		||||
                                </Setter.Value>
 | 
			
		||||
                            </Setter>
 | 
			
		||||
                        </Style>
 | 
			
		||||
                    </ControlTemplate.Resources>
 | 
			
		||||
                    <Border Background="{TemplateBinding Background}" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}">
 | 
			
		||||
                        <Grid x:Name="Root">
 | 
			
		||||
                            <Grid.ColumnDefinitions>
 | 
			
		||||
                                <ColumnDefinition Width="auto"/>
 | 
			
		||||
                                <ColumnDefinition Width="auto"/>
 | 
			
		||||
                                <ColumnDefinition />
 | 
			
		||||
                                <ColumnDefinition Width="auto"/>
 | 
			
		||||
                            </Grid.ColumnDefinitions>
 | 
			
		||||
                            <Border x:Name="IconView" Width="{Binding ActualHeight, ElementName=Root}">
 | 
			
		||||
                                <Image Margin="{TemplateBinding Padding}" VerticalAlignment="Center" HorizontalAlignment="Center"
 | 
			
		||||
                               Source="{Binding Icon, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/>
 | 
			
		||||
                            </Border>
 | 
			
		||||
                            <TextBlock x:Name="TitleBar" Grid.Column="1" FontSize="{TemplateBinding FontSize}" Foreground="{TemplateBinding Foreground}"
 | 
			
		||||
                               Margin="{TemplateBinding Padding}" VerticalAlignment="Center" HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
 | 
			
		||||
                               Text="{Binding Title, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}"/>
 | 
			
		||||
                            <Border x:Name="Container" Grid.Column="2" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"/>
 | 
			
		||||
                            <StackPanel x:Name="Controller" Grid.Column="3" Orientation="Horizontal">
 | 
			
		||||
                                <Button x:Name="Minimize" VerticalAlignment="Stretch" Style="{StaticResource controlButtonStyle}" Cursor="Hand"
 | 
			
		||||
                                Padding="{TemplateBinding Padding}" Width="{Binding ActualHeight, ElementName=Root}">
 | 
			
		||||
                                    <Viewbox Stretch="Uniform">
 | 
			
		||||
                                        <Path Width="1024" Height="1024" Stroke="{TemplateBinding Foreground}" Fill="{TemplateBinding Foreground}" Data="M917.333333 554.666667H106.666667a21.333333 21.333333 0 0 1 0-42.666667h810.666666a21.333333 21.333333 0 0 1 0 42.666667z"/>
 | 
			
		||||
                                    </Viewbox>
 | 
			
		||||
                                </Button>
 | 
			
		||||
                                <Button x:Name="Maximize" VerticalAlignment="Stretch" Style="{StaticResource controlButtonStyle}" Cursor="Hand"
 | 
			
		||||
                                Padding="{TemplateBinding Padding}" Width="{Binding ActualHeight, ElementName=Root}">
 | 
			
		||||
                                    <Viewbox Stretch="Uniform">
 | 
			
		||||
                                        <Path Width="1024" Height="1024" Stroke="{TemplateBinding Foreground}" Fill="{TemplateBinding Foreground}" Data="M714.666667 256H138.666667a53.393333 53.393333 0 0 0-53.333334 53.333333v576a53.393333 53.393333 0 0 0 53.333334 53.333334h576a53.393333 53.393333 0 0 0 53.333333-53.333334V309.333333a53.393333 53.393333 0 0 0-53.333333-53.333333z m10.666666 629.333333a10.666667 10.666667 0 0 1-10.666666 10.666667H138.666667a10.666667 10.666667 0 0 1-10.666667-10.666667V309.333333a10.666667 10.666667 0 0 1 10.666667-10.666666h576a10.666667 10.666667 0 0 1 10.666666 10.666666z m213.333334-746.666666v565.333333a21.333333 21.333333 0 0 1-42.666667 0V138.666667a10.666667 10.666667 0 0 0-10.666667-10.666667H320a21.333333 21.333333 0 0 1 0-42.666667h565.333333a53.393333 53.393333 0 0 1 53.333334 53.333334z"/>
 | 
			
		||||
                                    </Viewbox>
 | 
			
		||||
                                </Button>
 | 
			
		||||
                                <Button x:Name="CloseWin" VerticalAlignment="Stretch" Style="{StaticResource controlButtonStyle}" Cursor="Hand"
 | 
			
		||||
                                Padding="{TemplateBinding Padding}" Width="{Binding ActualHeight, ElementName=Root}">
 | 
			
		||||
                                    <Viewbox Stretch="Uniform">
 | 
			
		||||
                                        <Path Width="1024" Height="1024" Stroke="{TemplateBinding Foreground}" Fill="{TemplateBinding Foreground}" Data="M542.173333 512l347.58-347.58a21.333333 21.333333 0 1 0-30.173333-30.173333L512 481.826667 164.42 134.246667a21.333333 21.333333 0 0 0-30.173333 30.173333L481.826667 512l-347.58 347.58a21.333333 21.333333 0 0 0 30.173333 30.173333L512 542.173333l347.58 347.58a21.333333 21.333333 0 0 0 30.173333-30.173333z"/>
 | 
			
		||||
                                    </Viewbox>
 | 
			
		||||
                                </Button>
 | 
			
		||||
                            </StackPanel>
 | 
			
		||||
                        </Grid>
 | 
			
		||||
                    </Border>
 | 
			
		||||
                </ControlTemplate>
 | 
			
		||||
            </Setter.Value>
 | 
			
		||||
        </Setter>
 | 
			
		||||
    </Style>
 | 
			
		||||
    
 | 
			
		||||
    <Style TargetType="{x:Type local:ElegantWindow}">
 | 
			
		||||
        <Setter Property="Template">
 | 
			
		||||
            <Setter.Value>
 | 
			
		||||
                <ControlTemplate TargetType="{x:Type local:ElegantWindow}">
 | 
			
		||||
                    <Border Background="{TemplateBinding Background}"
 | 
			
		||||
                            BorderBrush="{TemplateBinding BorderBrush}"
 | 
			
		||||
                            BorderThickness="{TemplateBinding BorderThickness}">
 | 
			
		||||
                    </Border>
 | 
			
		||||
                </ControlTemplate>
 | 
			
		||||
            </Setter.Value>
 | 
			
		||||
        </Setter>
 | 
			
		||||
    </Style>
 | 
			
		||||
</ResourceDictionary>
 | 
			
		||||
							
								
								
									
										46
									
								
								DeedyDesigner/Deedy.Testing/Waiting.xaml
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								DeedyDesigner/Deedy.Testing/Waiting.xaml
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,46 @@
 | 
			
		||||
<Window x:Class="Deedy.Waiting"
 | 
			
		||||
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
 | 
			
		||||
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
 | 
			
		||||
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
 | 
			
		||||
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
 | 
			
		||||
        xmlns:sys="clr-namespace:System;assembly=mscorlib"
 | 
			
		||||
        xmlns:local="clr-namespace:Deedy"
 | 
			
		||||
        mc:Ignorable="d"
 | 
			
		||||
        Title="Waiting" Margin="0,0,0,32" Height="200" Width="640" Topmost="True" WindowStartupLocation="CenterScreen" WindowState="Maximized" Background="Transparent"
 | 
			
		||||
        WindowStyle="None" AllowsTransparency="True" DataContext="{Binding Mode=OneWay, RelativeSource={RelativeSource Self}}" ShowInTaskbar="False">
 | 
			
		||||
    <DockPanel>
 | 
			
		||||
        <Border MinHeight="0" DockPanel.Dock="Bottom" IsHitTestVisible="False"/>
 | 
			
		||||
        <Border Background="#20000000" x:Name="view">
 | 
			
		||||
            <DockPanel HorizontalAlignment="Center" VerticalAlignment="Center" MinHeight="120" MinWidth="600" Background="{DynamicResource BGTitle}">
 | 
			
		||||
                <Border x:Name="cancelBar" d:Visibility="Visible" Visibility="Collapsed" DockPanel.Dock="Top" Height="40" Background="{DynamicResource BGMenu}">
 | 
			
		||||
                    <Button Content="取消任务" Click="Button_取消按钮被点击_Click" FontSize="18" Foreground="{DynamicResource ButFGCareful}"/>
 | 
			
		||||
                </Border>
 | 
			
		||||
                <Grid DockPanel.Dock="Bottom" Height="40">
 | 
			
		||||
                    <ProgressBar x:Name="pbProgressBar" BorderThickness="0" IsIndeterminate="True" Background="{DynamicResource BGHyaline}"/>
 | 
			
		||||
                    <DockPanel>
 | 
			
		||||
                        <TextBlock DockPanel.Dock="Right" Margin="0,0,12,0" VerticalAlignment="Center" Foreground="{DynamicResource FGHighlight}" Text="%"
 | 
			
		||||
                       Visibility="{Binding ShowProgress,Mode=OneWay,Converter={StaticResource bool2VisibilityConverter}}"/>
 | 
			
		||||
                        <TextBlock DockPanel.Dock="Right" Margin="12,0,12,0" VerticalAlignment="Center" Foreground="{DynamicResource FGHighlight}" Text="{Binding Value, ElementName=pbProgressBar}"
 | 
			
		||||
                       Visibility="{Binding ShowProgress,Mode=OneWay,Converter={StaticResource bool2VisibilityConverter}}"/>
 | 
			
		||||
                        <TextBlock Margin="12,0,12,0" VerticalAlignment="Center" Foreground="{DynamicResource FGKeynote}" Text="当前任务处理比较耗时,可能需要处理很长时间,请耐心等待..."/>
 | 
			
		||||
                    </DockPanel>
 | 
			
		||||
                    <ItemsControl Background="{DynamicResource BGTitle}" Visibility="{Binding OptionsVisibility,Mode=OneWay}" d:Visibility="Visible" ItemsSource="{Binding Options}">
 | 
			
		||||
                        <ItemsControl.ItemsPanel>
 | 
			
		||||
                            <ItemsPanelTemplate>
 | 
			
		||||
                                <UniformGrid Rows="1"/>
 | 
			
		||||
                            </ItemsPanelTemplate>
 | 
			
		||||
                        </ItemsControl.ItemsPanel>
 | 
			
		||||
                        <ItemsControl.ItemTemplate>
 | 
			
		||||
                            <DataTemplate DataType="{x:Type sys:String}">
 | 
			
		||||
                                <Button Content="{Binding}" Click="Button_Click" IsDefault="True"/>
 | 
			
		||||
                            </DataTemplate>
 | 
			
		||||
                        </ItemsControl.ItemTemplate>
 | 
			
		||||
                    </ItemsControl>
 | 
			
		||||
                </Grid>
 | 
			
		||||
                <Border Padding="20" BorderBrush="{DynamicResource BBHighlight}" BorderThickness="0,0,0,0.5">
 | 
			
		||||
                    <TextBlock Text="{Binding HintMessage,Mode=OneWay}" FontSize="20" TextWrapping="Wrap" VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="{DynamicResource FGTitle}"/>
 | 
			
		||||
                </Border>
 | 
			
		||||
            </DockPanel>
 | 
			
		||||
        </Border>
 | 
			
		||||
    </DockPanel>
 | 
			
		||||
</Window>
 | 
			
		||||
							
								
								
									
										104
									
								
								DeedyDesigner/Deedy.Testing/Waiting.xaml.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										104
									
								
								DeedyDesigner/Deedy.Testing/Waiting.xaml.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,104 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Collections.ObjectModel;
 | 
			
		||||
using System.Diagnostics;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using System.Windows;
 | 
			
		||||
using System.Windows.Controls;
 | 
			
		||||
using System.Windows.Data;
 | 
			
		||||
using System.Windows.Documents;
 | 
			
		||||
using System.Windows.Input;
 | 
			
		||||
using System.Windows.Media;
 | 
			
		||||
using System.Windows.Media.Imaging;
 | 
			
		||||
using System.Windows.Shapes;
 | 
			
		||||
 | 
			
		||||
namespace Deedy
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// Waiting.xaml 的交互逻辑
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    public partial class Waiting : Window
 | 
			
		||||
    {
 | 
			
		||||
        private Func<bool>? CancelHandler;
 | 
			
		||||
        public ObservableCollection<string> Options { get; private set; } = new ObservableCollection<string>();
 | 
			
		||||
        public Waiting()
 | 
			
		||||
        {
 | 
			
		||||
            InitializeComponent();
 | 
			
		||||
            Options.Add("确定");
 | 
			
		||||
            if (Debugger.IsAttached) this.view.Background = null;
 | 
			
		||||
        }
 | 
			
		||||
        public Waiting(string? hintMsg = null, int process = -1, Func<bool>? cancelHandler = null) : this()
 | 
			
		||||
        {
 | 
			
		||||
            this.HintMessage = hintMsg ?? "系统正忙,请稍等...";
 | 
			
		||||
            if (process >= 0) this.SetProgress(process);
 | 
			
		||||
            this.OptionsVisibility = Visibility.Collapsed;
 | 
			
		||||
            CancelHandler = cancelHandler;
 | 
			
		||||
            if (CancelHandler != null) this.cancelBar.Visibility = Visibility.Visible;
 | 
			
		||||
        }
 | 
			
		||||
        public Waiting(string? hintMsg = null, params string[] options) : this(hintMsg, -1)
 | 
			
		||||
        {
 | 
			
		||||
            if (options != null && options.Length > 0)
 | 
			
		||||
            {
 | 
			
		||||
                this.Options.Clear();
 | 
			
		||||
                foreach (string option in options)
 | 
			
		||||
                    this.Options.Add(option);
 | 
			
		||||
            }
 | 
			
		||||
            this.OptionsVisibility = Visibility.Visible;
 | 
			
		||||
        }
 | 
			
		||||
        public string HintMessage
 | 
			
		||||
        {
 | 
			
		||||
            get { return (string)GetValue(HintMessageProperty); }
 | 
			
		||||
            set { SetValue(HintMessageProperty, value); }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Using a DependencyProperty as the backing store for HintMessage.  This enables animation, styling, binding, etc...
 | 
			
		||||
        public static readonly DependencyProperty HintMessageProperty =
 | 
			
		||||
            DependencyProperty.Register("HintMessage", typeof(string), typeof(Waiting), new PropertyMetadata("系统正忙,请稍等..."));
 | 
			
		||||
 | 
			
		||||
        public bool ShowProgress
 | 
			
		||||
        {
 | 
			
		||||
            get { return (bool)GetValue(ShowProgressProperty); }
 | 
			
		||||
            set { SetValue(ShowProgressProperty, value); }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Using a DependencyProperty as the backing store for ShowProgress.  This enables animation, styling, binding, etc...
 | 
			
		||||
        public static readonly DependencyProperty ShowProgressProperty =
 | 
			
		||||
            DependencyProperty.Register("ShowProgress", typeof(bool), typeof(Waiting), new PropertyMetadata(false));
 | 
			
		||||
        public string Option { get; private set; } = "";
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public Visibility OptionsVisibility
 | 
			
		||||
        {
 | 
			
		||||
            get { return (Visibility)GetValue(OptionsVisibilityProperty); }
 | 
			
		||||
            set { SetValue(OptionsVisibilityProperty, value); }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Using a DependencyProperty as the backing store for OptionsVisibility.  This enables animation, styling, binding, etc...
 | 
			
		||||
        public static readonly DependencyProperty OptionsVisibilityProperty =
 | 
			
		||||
            DependencyProperty.Register("OptionsVisibility", typeof(Visibility), typeof(Waiting), new PropertyMetadata(Visibility.Collapsed));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public void SetProgress(double progress, string hintMsg = "")
 | 
			
		||||
        {
 | 
			
		||||
            this.ShowProgress = true;
 | 
			
		||||
            if (!string.IsNullOrEmpty(hintMsg)) this.HintMessage = hintMsg;
 | 
			
		||||
            this.OptionsVisibility = Visibility.Collapsed;
 | 
			
		||||
            this.pbProgressBar.Value = progress;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void Button_Click(object sender, RoutedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            Button btn = (Button)sender;
 | 
			
		||||
            this.Option = (btn.Content as string) ?? "";
 | 
			
		||||
            this.DialogResult = true;
 | 
			
		||||
            this.Close();
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        private void Button_取消按钮被点击_Click(object sender, RoutedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.CancelHandler?.Invoke() == true) this.Close();
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
							
								
								
									
										239
									
								
								DeedyDesigner/Deedy.Testing/WindowDecorator.cs
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										239
									
								
								DeedyDesigner/Deedy.Testing/WindowDecorator.cs
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,239 @@
 | 
			
		||||
using System;
 | 
			
		||||
using System.Collections.Generic;
 | 
			
		||||
using System.Linq;
 | 
			
		||||
using System.Text;
 | 
			
		||||
using System.Threading.Tasks;
 | 
			
		||||
using System.Windows;
 | 
			
		||||
using System.Windows.Controls;
 | 
			
		||||
using System.Windows.Data;
 | 
			
		||||
using System.Windows.Documents;
 | 
			
		||||
using System.Windows.Input;
 | 
			
		||||
using System.Windows.Markup;
 | 
			
		||||
using System.Windows.Media;
 | 
			
		||||
using System.Windows.Media.Imaging;
 | 
			
		||||
using System.Windows.Navigation;
 | 
			
		||||
using System.Windows.Shapes;
 | 
			
		||||
using System.Windows.Shell;
 | 
			
		||||
 | 
			
		||||
namespace Deedy
 | 
			
		||||
{
 | 
			
		||||
    /// <summary>
 | 
			
		||||
    /// 按照步骤 1a 或 1b 操作,然后执行步骤 2 以在 XAML 文件中使用此自定义控件。
 | 
			
		||||
    ///
 | 
			
		||||
    /// 步骤 1a) 在当前项目中存在的 XAML 文件中使用该自定义控件。
 | 
			
		||||
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
 | 
			
		||||
    /// 元素中:
 | 
			
		||||
    ///
 | 
			
		||||
    ///     xmlns:MyNamespace="clr-namespace:ReoKM"
 | 
			
		||||
    ///
 | 
			
		||||
    ///
 | 
			
		||||
    /// 步骤 1b) 在其他项目中存在的 XAML 文件中使用该自定义控件。
 | 
			
		||||
    /// 将此 XmlNamespace 特性添加到要使用该特性的标记文件的根
 | 
			
		||||
    /// 元素中:
 | 
			
		||||
    ///
 | 
			
		||||
    ///     xmlns:MyNamespace="clr-namespace:ReoKM;assembly=ReoKM"
 | 
			
		||||
    ///
 | 
			
		||||
    /// 您还需要添加一个从 XAML 文件所在的项目到此项目的项目引用,
 | 
			
		||||
    /// 并重新生成以避免编译错误:
 | 
			
		||||
    ///
 | 
			
		||||
    ///     在解决方案资源管理器中右击目标项目,然后依次单击
 | 
			
		||||
    ///     “添加引用”->“项目”->[浏览查找并选择此项目]
 | 
			
		||||
    ///
 | 
			
		||||
    ///
 | 
			
		||||
    /// 步骤 2)
 | 
			
		||||
    /// 继续操作并在 XAML 文件中使用控件。
 | 
			
		||||
    ///
 | 
			
		||||
    ///     <MyNamespace:WindowDecorator/>
 | 
			
		||||
    ///
 | 
			
		||||
    /// </summary>
 | 
			
		||||
    [ContentProperty("Child")]
 | 
			
		||||
    [TemplatePart(Name = "IconView", Type = typeof(Border))]
 | 
			
		||||
    [TemplatePart(Name = "TitleBar", Type = typeof(TextBlock))]
 | 
			
		||||
    [TemplatePart(Name = "Minimize", Type = typeof(Button))]
 | 
			
		||||
    [TemplatePart(Name = "Maximize", Type = typeof(Button))]
 | 
			
		||||
    [TemplatePart(Name = "CloseWin", Type = typeof(Button))]
 | 
			
		||||
    [TemplatePart(Name = "Controller", Type = typeof(Panel))]
 | 
			
		||||
    [TemplatePart(Name = "Container", Type = typeof(Decorator))]
 | 
			
		||||
    public class WindowDecorator : Control
 | 
			
		||||
    {
 | 
			
		||||
        static WindowDecorator()
 | 
			
		||||
        {
 | 
			
		||||
            DefaultStyleKeyProperty.OverrideMetadata(typeof(WindowDecorator), new FrameworkPropertyMetadata(typeof(WindowDecorator)));
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public Brush HoverBrush
 | 
			
		||||
        {
 | 
			
		||||
            get { return (Brush)GetValue(HoverBrushProperty); }
 | 
			
		||||
            set { SetValue(HoverBrushProperty, value); }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static readonly DependencyProperty HoverBrushProperty =
 | 
			
		||||
            DependencyProperty.Register("HoverBrush", typeof(Brush), typeof(WindowDecorator), new PropertyMetadata(null));
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
        public UIElement Child
 | 
			
		||||
        {
 | 
			
		||||
            get { return (UIElement)GetValue(ChildProperty); }
 | 
			
		||||
            set { SetValue(ChildProperty, value); }
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        public static readonly DependencyProperty ChildProperty =
 | 
			
		||||
            DependencyProperty.Register("Child", typeof(UIElement), typeof(WindowDecorator), new PropertyMetadata(null, (d, e) =>
 | 
			
		||||
            {
 | 
			
		||||
                WindowDecorator windowDecorator = (WindowDecorator)d;
 | 
			
		||||
                if (e.NewValue != null)
 | 
			
		||||
                {
 | 
			
		||||
                    if (windowDecorator.Container != null)
 | 
			
		||||
                        windowDecorator.Container.Child = e.NewValue as UIElement;
 | 
			
		||||
                }
 | 
			
		||||
            }));
 | 
			
		||||
 | 
			
		||||
        private Panel? Controller;
 | 
			
		||||
        private Decorator? Container;
 | 
			
		||||
        private Button? Minimize;
 | 
			
		||||
        private Button? Maximize;
 | 
			
		||||
        private Button? CloseWin;
 | 
			
		||||
        private TextBlock? TitleBar;
 | 
			
		||||
        private Border? IconView;
 | 
			
		||||
 | 
			
		||||
        private Window? Target;
 | 
			
		||||
        private WindowChrome? Chrome;
 | 
			
		||||
        private Decorator? Decorator;
 | 
			
		||||
 | 
			
		||||
        private static bool IsNeedOverrideMetadata = true;
 | 
			
		||||
        public WindowDecorator() { }
 | 
			
		||||
        public void OnAttached(Window target, Decorator decorator)
 | 
			
		||||
        {
 | 
			
		||||
            //这是第【1】步
 | 
			
		||||
            if (target == null) throw new ArgumentNullException("窗体装饰器[WindowDecorator]对象不可以附加到一个空的Window对象上!");
 | 
			
		||||
            if (decorator == null) throw new ArgumentNullException("窗体装饰器[WindowDecorator]对象需要一个用于放置的容器!");
 | 
			
		||||
            this.Target = target;
 | 
			
		||||
            this.Decorator = decorator;
 | 
			
		||||
            this.Decorator.Child = this;
 | 
			
		||||
            this.Target.StateChanged += Target_StateChanged;
 | 
			
		||||
            this.Target.Loaded += Target_Loaded;
 | 
			
		||||
            if (IsNeedOverrideMetadata)
 | 
			
		||||
            {
 | 
			
		||||
                Window.WindowStyleProperty.OverrideMetadata(this.Target.GetType(), new FrameworkPropertyMetadata((d, e) => this.AdjustVisual()));
 | 
			
		||||
                Window.ResizeModeProperty.OverrideMetadata(this.Target.GetType(), new FrameworkPropertyMetadata((d, e) => this.AdjustVisual()));
 | 
			
		||||
                IsNeedOverrideMetadata = false;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        public override void OnApplyTemplate()
 | 
			
		||||
        {
 | 
			
		||||
            base.OnApplyTemplate();
 | 
			
		||||
            //这是第【2】步
 | 
			
		||||
            this.Controller = GetTemplateChild("Controller") as Panel;
 | 
			
		||||
            this.Container = GetTemplateChild("Container") as Decorator;
 | 
			
		||||
            this.Minimize = GetTemplateChild("Minimize") as Button;
 | 
			
		||||
            this.Maximize = GetTemplateChild("Maximize") as Button;
 | 
			
		||||
            this.CloseWin = GetTemplateChild("CloseWin") as Button;
 | 
			
		||||
            this.IconView = GetTemplateChild("IconView") as Border;
 | 
			
		||||
            this.TitleBar = GetTemplateChild("TitleBar") as TextBlock;
 | 
			
		||||
        }
 | 
			
		||||
        private void Target_Loaded(object sender, RoutedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            if (this.Background == BackgroundProperty.DefaultMetadata.DefaultValue) this.SetBinding(BackgroundProperty, new Binding() { Source = this.Target, Path = new PropertyPath(BackgroundProperty.Name) });
 | 
			
		||||
            if (this.BorderBrush == BorderBrushProperty.DefaultMetadata.DefaultValue) this.SetBinding(BorderBrushProperty, new Binding() { Source = this.Target, Path = new PropertyPath(BorderBrushProperty.Name) });
 | 
			
		||||
            //这是第【3】步
 | 
			
		||||
            this.Chrome = new WindowChrome() { CaptionHeight = this.ActualHeight };
 | 
			
		||||
            WindowChrome.SetWindowChrome(this.Target, this.Chrome);
 | 
			
		||||
            WindowChrome.SetIsHitTestVisibleInChrome(this.Container, true);
 | 
			
		||||
            WindowChrome.SetIsHitTestVisibleInChrome(this.Controller, true);
 | 
			
		||||
            if (this.Container != null) this.Container.Child = this.Child;
 | 
			
		||||
            if (this.Controller != null)
 | 
			
		||||
            {
 | 
			
		||||
                foreach (var c in this.Controller.Children)
 | 
			
		||||
                {
 | 
			
		||||
                    Button? button = c as Button;
 | 
			
		||||
                    button?.AddHandler(Button.ClickEvent, new RoutedEventHandler(this.CommandButton_Click));
 | 
			
		||||
                    button?.AddHandler(Button.MouseEnterEvent, new RoutedEventHandler((s, e) => ((Button)e.Source).Background = this.HoverBrush));
 | 
			
		||||
                    button?.AddHandler(Button.MouseLeaveEvent, new RoutedEventHandler((s, e) => ((Button)e.Source).Background = Brushes.Transparent));
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
            this.AdjustVisual();
 | 
			
		||||
            this.AdjustMargin();
 | 
			
		||||
        }
 | 
			
		||||
        public void OnDetaching()
 | 
			
		||||
        {
 | 
			
		||||
            if (this.Target != null)
 | 
			
		||||
            {
 | 
			
		||||
                this.Target.StateChanged -= this.Target_StateChanged;
 | 
			
		||||
                this.Target.Loaded -= this.Target_Loaded;
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        private void AdjustVisual()
 | 
			
		||||
        {
 | 
			
		||||
            if (this.Target != null)
 | 
			
		||||
            {
 | 
			
		||||
                if (this.Controller != null) this.Controller.Visibility = Visibility.Visible;
 | 
			
		||||
                if (this.Minimize != null) this.Minimize.Visibility = Visibility.Visible;
 | 
			
		||||
                if (this.Maximize != null) this.Maximize.Visibility = Visibility.Visible;
 | 
			
		||||
                if (this.CloseWin != null) this.CloseWin.Visibility = Visibility.Visible;
 | 
			
		||||
                if (this.IconView != null) this.IconView.Visibility = Visibility.Visible;
 | 
			
		||||
                if (this.TitleBar != null) this.TitleBar.Visibility = Visibility.Visible;
 | 
			
		||||
 | 
			
		||||
                if (this.Target.ResizeMode == ResizeMode.NoResize)
 | 
			
		||||
                {
 | 
			
		||||
                    if (this.Minimize != null) this.Minimize.Visibility = Visibility.Collapsed;
 | 
			
		||||
                    if (this.Maximize != null) this.Maximize.Visibility = Visibility.Collapsed;
 | 
			
		||||
                }
 | 
			
		||||
                if (this.Target.ResizeMode == ResizeMode.CanMinimize)
 | 
			
		||||
                {
 | 
			
		||||
                    if (this.Maximize != null) this.Maximize.Visibility = Visibility.Collapsed;
 | 
			
		||||
                }
 | 
			
		||||
                if (this.Target.WindowStyle == WindowStyle.None)
 | 
			
		||||
                {
 | 
			
		||||
                    if (this.IconView != null) this.IconView.Visibility = Visibility.Collapsed;
 | 
			
		||||
                    if (this.TitleBar != null) this.TitleBar.Visibility = Visibility.Collapsed;
 | 
			
		||||
                    if (this.Controller != null) this.Controller.Visibility = Visibility.Collapsed;
 | 
			
		||||
                }
 | 
			
		||||
                if (this.Target.WindowStyle == WindowStyle.ToolWindow)
 | 
			
		||||
                {
 | 
			
		||||
                    if (this.Controller != null) this.Controller.Visibility = Visibility.Collapsed;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        private void AdjustMargin()
 | 
			
		||||
        {
 | 
			
		||||
            if (this.Target != null)
 | 
			
		||||
            {
 | 
			
		||||
                var winContent = this.Target.Content as FrameworkElement;
 | 
			
		||||
                if (winContent == null) return;
 | 
			
		||||
                if (this.Target.WindowState == WindowState.Maximized)
 | 
			
		||||
                    winContent.Margin = new Thickness(8);
 | 
			
		||||
                else winContent.Margin = new Thickness(0);
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        private void Target_StateChanged(object? sender, EventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            this.AdjustMargin();
 | 
			
		||||
        }
 | 
			
		||||
        private void CommandButton_Click(object sender, RoutedEventArgs e)
 | 
			
		||||
        {
 | 
			
		||||
            Button? button = sender as Button;
 | 
			
		||||
            if (button != null)
 | 
			
		||||
            {
 | 
			
		||||
                switch (button.Name)
 | 
			
		||||
                {
 | 
			
		||||
                    case "Minimize":
 | 
			
		||||
                        if (this.Target != null) this.Target.WindowState = WindowState.Minimized;
 | 
			
		||||
                        break;
 | 
			
		||||
                    case "Maximize":
 | 
			
		||||
                        {
 | 
			
		||||
                            if (this.Target != null)
 | 
			
		||||
                            {
 | 
			
		||||
                                if (this.Target.WindowState == WindowState.Maximized || this.Target.WindowState == WindowState.Minimized)
 | 
			
		||||
                                    this.Target.WindowState = WindowState.Normal;
 | 
			
		||||
                                else this.Target.WindowState = WindowState.Maximized;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                        break;
 | 
			
		||||
                    default:
 | 
			
		||||
                        this.Target?.Close();
 | 
			
		||||
                        break;
 | 
			
		||||
                }
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user