Compare commits
24 Commits
Author | SHA1 | Date | |
---|---|---|---|
![]() |
730bbcae25 | ||
![]() |
36433178c2 | ||
![]() |
0a12d33d15 | ||
![]() |
5eb8c25799 | ||
![]() |
49b1ebcd5c | ||
![]() |
9ab836ff44 | ||
![]() |
a1db3807ff | ||
![]() |
6631fec5e6 | ||
![]() |
807cbdf300 | ||
![]() |
507e844275 | ||
![]() |
b79e63da71 | ||
![]() |
235e8ec59e | ||
![]() |
db457dac7b | ||
![]() |
2004876770 | ||
![]() |
763a3893d6 | ||
![]() |
a6fc04e737 | ||
![]() |
bc5e6be81e | ||
![]() |
c439a46e38 | ||
![]() |
8decf9e554 | ||
![]() |
40efe5292f | ||
![]() |
313f8fd79b | ||
![]() |
25ce5d78ba | ||
![]() |
2cd339388f | ||
![]() |
f673ced43a |
2
AndroidTest/Resources/Resource.designer.cs
generated
2
AndroidTest/Resources/Resource.designer.cs
generated
@ -14,7 +14,7 @@ namespace AndroidTest
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.2.2.120")]
|
||||||
public partial class Resource
|
public partial class Resource
|
||||||
{
|
{
|
||||||
|
|
||||||
|
2
CPF.Android/Resources/Resource.designer.cs
generated
2
CPF.Android/Resources/Resource.designer.cs
generated
@ -14,7 +14,7 @@ namespace CPF.Android
|
|||||||
{
|
{
|
||||||
|
|
||||||
|
|
||||||
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "1.0.0.0")]
|
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Android.Build.Tasks", "13.2.2.120")]
|
||||||
public partial class Resource
|
public partial class Resource
|
||||||
{
|
{
|
||||||
|
|
||||||
|
21
CPF.Toolkit.Demo/CPF.Toolkit.Demo.csproj
Normal file
21
CPF.Toolkit.Demo/CPF.Toolkit.Demo.csproj
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>WinExe</OutputType>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
|
<Nullable>enable</Nullable>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\CPF.Linux\CPF.Linux.csproj" />
|
||||||
|
<ProjectReference Include="..\CPF.Mac\CPF.Mac.csproj" />
|
||||||
|
<ProjectReference Include="..\CPF.Skia\CPF.Skia.csproj" />
|
||||||
|
<ProjectReference Include="..\CPF.Toolkit\CPF.Toolkit.csproj" />
|
||||||
|
<ProjectReference Include="..\CPF.Windows\CPF.Windows.csproj" />
|
||||||
|
<ProjectReference Include="..\CPF\CPF.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
145
CPF.Toolkit.Demo/MainView.cs
Normal file
145
CPF.Toolkit.Demo/MainView.cs
Normal file
@ -0,0 +1,145 @@
|
|||||||
|
using CPF;
|
||||||
|
using CPF.Animation;
|
||||||
|
using CPF.Charts;
|
||||||
|
using CPF.Controls;
|
||||||
|
using CPF.Drawing;
|
||||||
|
using CPF.Shapes;
|
||||||
|
using CPF.Styling;
|
||||||
|
using CPF.Svg;
|
||||||
|
using CPF.Toolkit.Controls;
|
||||||
|
using CPF.Toolkit.Dialogs;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit.Demo
|
||||||
|
{
|
||||||
|
public class MainView : Window
|
||||||
|
{
|
||||||
|
MainViewModel vm = new MainViewModel();
|
||||||
|
protected override void InitializeComponent()
|
||||||
|
{
|
||||||
|
Title = "标题";
|
||||||
|
Width = 1280;
|
||||||
|
Height = 720;
|
||||||
|
Background = null;
|
||||||
|
this.DataContext = this.CommandContext = vm;
|
||||||
|
this.CanResize = true;
|
||||||
|
|
||||||
|
Children.Add(new WindowFrame(this, new WrapPanel
|
||||||
|
{
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "alert",
|
||||||
|
Commands = { { nameof(Button.Click),(s,e) => vm.Dialog.Alert("这是一条测试消息") } }
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "Sucess",
|
||||||
|
Commands = { { nameof(Button.Click),(s,e) => vm.Dialog.Sucess("这是一条测试消息") } }
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "Error",
|
||||||
|
Commands = { { nameof(Button.Click),(s,e) => vm.Dialog.Error("这是一条测试消息") } }
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "Ask",
|
||||||
|
Commands = { { nameof(Button.Click),(s,e) => vm.Dialog.Ask("这是一条测试消息") } }
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "Warn",
|
||||||
|
Commands = { { nameof(Button.Click),(s,e) => vm.Dialog.Warn("这是一条测试消息") } }
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "关闭窗体",
|
||||||
|
Commands = { { nameof(Button.Click),(s,e) => vm.Test() } }
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "loading",
|
||||||
|
Commands = { { nameof(Button.Click),(s,e) => vm.LoadingTest() } }
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "AsyncButton",
|
||||||
|
Commands =
|
||||||
|
{
|
||||||
|
{ nameof(Button.AsyncClick),async (s,e) => await this.vm.AsyncClick() }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "Mdi",
|
||||||
|
Commands =
|
||||||
|
{
|
||||||
|
{ nameof(Button.Click), (s,e) => new TestMdiView().Show() }
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
new Panel
|
||||||
|
{
|
||||||
|
},
|
||||||
|
new PageControl
|
||||||
|
{
|
||||||
|
Height = 35,
|
||||||
|
PageIndex = 1,
|
||||||
|
PageCount = 100,
|
||||||
|
Width = "100%",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MainViewModel : ViewModelBase
|
||||||
|
{
|
||||||
|
public void Test()
|
||||||
|
{
|
||||||
|
this.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnClose(ClosingEventArgs e)
|
||||||
|
{
|
||||||
|
e.Cancel = this.Dialog.Ask("确定要关闭吗") != "确定";
|
||||||
|
base.OnClose(e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public async void LoadingTest()
|
||||||
|
{
|
||||||
|
await this.ShowLoading(async () =>
|
||||||
|
{
|
||||||
|
await Task.Delay(1000);
|
||||||
|
Debug.WriteLine(1);
|
||||||
|
await Task.Delay(1000);
|
||||||
|
Debug.WriteLine(2);
|
||||||
|
await Task.Delay(1000);
|
||||||
|
Debug.WriteLine(3);
|
||||||
|
});
|
||||||
|
//await this.ShowLoading(Task.Delay(3000));
|
||||||
|
|
||||||
|
//var result = await this.ShowLoading(async () =>
|
||||||
|
//{
|
||||||
|
// await Task.Delay(5000);
|
||||||
|
// return "test";
|
||||||
|
//});
|
||||||
|
this.Dialog.Sucess("test");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task AsyncClick()
|
||||||
|
{
|
||||||
|
await Task.Delay(3000);
|
||||||
|
this.Dialog.Alert("test");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
23
CPF.Toolkit.Demo/Program.cs
Normal file
23
CPF.Toolkit.Demo/Program.cs
Normal file
@ -0,0 +1,23 @@
|
|||||||
|
using CPF.Controls;
|
||||||
|
using CPF.Platform;
|
||||||
|
using CPF.Skia;
|
||||||
|
using CPF.Toolkit.Dialogs;
|
||||||
|
using CPF.Windows;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit.Demo
|
||||||
|
{
|
||||||
|
internal class Program
|
||||||
|
{
|
||||||
|
[STAThread]
|
||||||
|
static void Main(string[] args)
|
||||||
|
{
|
||||||
|
Application.Initialize(
|
||||||
|
(OperatingSystemType.Windows, new WindowsPlatform(false), new SkiaDrawingFactory { })
|
||||||
|
, (OperatingSystemType.OSX, new CPF.Mac.MacPlatform(), new SkiaDrawingFactory { UseGPU = false })
|
||||||
|
, (OperatingSystemType.Linux, new CPF.Linux.LinuxPlatform(), new SkiaDrawingFactory { UseGPU = false })
|
||||||
|
);
|
||||||
|
|
||||||
|
Application.Run(ViewManager.View<MainView>());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
139
CPF.Toolkit.Demo/TestMdiView.cs
Normal file
139
CPF.Toolkit.Demo/TestMdiView.cs
Normal file
@ -0,0 +1,139 @@
|
|||||||
|
using CPF;
|
||||||
|
using CPF.Animation;
|
||||||
|
using CPF.Charts;
|
||||||
|
using CPF.Controls;
|
||||||
|
using CPF.Drawing;
|
||||||
|
using CPF.Shapes;
|
||||||
|
using CPF.Styling;
|
||||||
|
using CPF.Svg;
|
||||||
|
using CPF.Toolkit.Controls;
|
||||||
|
using CPF.Toolkit.Dialogs;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit.Demo
|
||||||
|
{
|
||||||
|
public class TestMdiView : Window
|
||||||
|
{
|
||||||
|
protected override void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.CanResize = true;
|
||||||
|
this.Title = "标题";
|
||||||
|
this.Width = 1280;
|
||||||
|
this.Height = 720;
|
||||||
|
this.Background = null;
|
||||||
|
var frame = this.Children.Add(new WindowFrame(this, new Grid
|
||||||
|
{
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
RowDefinitions =
|
||||||
|
{
|
||||||
|
new RowDefinition{ Height = 30 },
|
||||||
|
new RowDefinition{ },
|
||||||
|
},
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new MdiHost
|
||||||
|
{
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Attacheds = { { Grid.RowIndex,1 } },
|
||||||
|
TaskBarPlacement = TaskBarPlacement.Top,
|
||||||
|
}.Assign(out var host),
|
||||||
|
new WrapPanel
|
||||||
|
{
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Height = "100%",
|
||||||
|
Content = "New Window",
|
||||||
|
[nameof(Button.Click)] = new CommandDescribe((s,e) => host.Children.Add(new M{ Title = $"Title{host.Children.Count}", })),
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Height = "100%",
|
||||||
|
Content = "任务栏居上",
|
||||||
|
[nameof(Button.Click)] = new CommandDescribe((s,e) => host.TaskBarPlacement = TaskBarPlacement.Top),
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Height = "100%",
|
||||||
|
Content = "任务栏居下",
|
||||||
|
[nameof(Button.Click)] = new CommandDescribe((s,e) => host.TaskBarPlacement = TaskBarPlacement.Bottom),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}));
|
||||||
|
//frame.CaptionBackgrund = "white";
|
||||||
|
//frame.CaptionForeground = "black";
|
||||||
|
//frame.ControlBoxStroke = "black";
|
||||||
|
frame.MaximizeBox = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class M : MdiWindow
|
||||||
|
{
|
||||||
|
protected override void InitializeComponent()
|
||||||
|
{
|
||||||
|
var vm = new MV { Dialog = new DialogService(this.Root as Window) };
|
||||||
|
this.DataContext = vm;
|
||||||
|
this.CommandContext = vm;
|
||||||
|
this.Content = new WrapPanel
|
||||||
|
{
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "close",
|
||||||
|
[nameof(Button.Click)] = new CommandDescribe((s,e) => vm.TestClose())
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "loading",
|
||||||
|
[nameof(Button.AsyncClick)] = new CommandDescribe(async (s,e) => await vm.LoadingTest()),
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "alert",
|
||||||
|
[nameof(Button.Click)] = new CommandDescribe( (s,e) => vm.TestAlert()),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class MV : ViewModelBase
|
||||||
|
{
|
||||||
|
public void TestClose()
|
||||||
|
{
|
||||||
|
this.Close();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void TestAlert()
|
||||||
|
{
|
||||||
|
this.Dialog.Warn("test");
|
||||||
|
}
|
||||||
|
|
||||||
|
public async Task LoadingTest()
|
||||||
|
{
|
||||||
|
var result = await this.ShowLoading(async () =>
|
||||||
|
{
|
||||||
|
await Task.Delay(3000);
|
||||||
|
return "ok";
|
||||||
|
});
|
||||||
|
Debug.WriteLine(result);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnClose(ClosingEventArgs e)
|
||||||
|
{
|
||||||
|
e.Cancel = this.Dialog.Ask("确定要关闭吗") != "确定";
|
||||||
|
base.OnClose(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
27
CPF.Toolkit/CPF.Toolkit.csproj
Normal file
27
CPF.Toolkit/CPF.Toolkit.csproj
Normal file
@ -0,0 +1,27 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Remove="Images\ask.png" />
|
||||||
|
<None Remove="Images\error.png" />
|
||||||
|
<None Remove="Images\sucess.png" />
|
||||||
|
<None Remove="Images\warn.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<EmbeddedResource Include="Images\ask.png" />
|
||||||
|
<EmbeddedResource Include="Images\error.png" />
|
||||||
|
<EmbeddedResource Include="Images\sucess.png" />
|
||||||
|
<EmbeddedResource Include="Images\warn.png" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\CPF\CPF.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.CSharp" Version="4.7.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
370
CPF.Toolkit/Controls/MdiHost.cs
Normal file
370
CPF.Toolkit/Controls/MdiHost.cs
Normal file
@ -0,0 +1,370 @@
|
|||||||
|
using CPF.Controls;
|
||||||
|
using CPF.Drawing;
|
||||||
|
using CPF.Platform;
|
||||||
|
using CPF.Shapes;
|
||||||
|
using CPF.Styling;
|
||||||
|
using CPF.Toolkit.Dialogs;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit.Controls
|
||||||
|
{
|
||||||
|
public class MdiHost : Grid
|
||||||
|
{
|
||||||
|
public MdiHost()
|
||||||
|
{
|
||||||
|
this.TaskBarList = new Collection<UIElement>();
|
||||||
|
this.Size = SizeField.Fill;
|
||||||
|
this.Background = "204,204,204";
|
||||||
|
base.RowDefinitions.Add(new RowDefinition { Height = GridLength.Star });
|
||||||
|
base.RowDefinitions.Add(new RowDefinition { Height = 35 });
|
||||||
|
base.Children.Add(this.host);
|
||||||
|
taskBar = base.Children.Add(new ListBox
|
||||||
|
{
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Background = "white",
|
||||||
|
BorderFill = "silver",
|
||||||
|
BorderThickness = new Thickness(0, 1, 0, 0),
|
||||||
|
BorderType = BorderType.BorderThickness,
|
||||||
|
ItemsPanel = new StackPanel { Orientation = Orientation.Horizontal },
|
||||||
|
ItemTemplate = new TaskBarItem
|
||||||
|
{
|
||||||
|
[nameof(TaskBarItem.CloseClick)] = new CommandDescribe((s, e) => (s.DataContext as MdiWindow).Close())
|
||||||
|
},
|
||||||
|
Items = this.TaskBarList,
|
||||||
|
[nameof(ListBox.SelectedValue)] = new BindingDescribe(this, nameof(this.SelectWindow), BindingMode.TwoWay),
|
||||||
|
}, row: 1);
|
||||||
|
this.host.PropertyChanged += Host_PropertyChanged;
|
||||||
|
this.host.UIElementAdded += Host_UIElementAdded;
|
||||||
|
this.host.UIElementRemoved += Host_UIElementRemoved;
|
||||||
|
}
|
||||||
|
readonly Dictionary<UIElement, MdiWindowRect> normalRect = [];
|
||||||
|
readonly Panel host = new() { Size = SizeField.Fill };
|
||||||
|
readonly ListBox taskBar;
|
||||||
|
Collection<UIElement> TaskBarList { get => GetValue<Collection<UIElement>>(); set => SetValue(value); }
|
||||||
|
public new UIElementCollection Children => host.Children;
|
||||||
|
public MdiWindow SelectWindow { get => GetValue<MdiWindow>(); set => SetValue(value); }
|
||||||
|
|
||||||
|
[PropertyMetadata(TaskBarPlacement.Bottom)]
|
||||||
|
public TaskBarPlacement TaskBarPlacement { get => GetValue<TaskBarPlacement>(); set => SetValue(value); }
|
||||||
|
|
||||||
|
protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue, PropertyMetadataAttribute propertyMetadata)
|
||||||
|
{
|
||||||
|
if (propertyName == nameof(this.SelectWindow) && this.SelectWindow != null)
|
||||||
|
{
|
||||||
|
this.Topping(this.SelectWindow);
|
||||||
|
this.SelectWindow.WindowState = this.normalRect[this.SelectWindow].OldState;
|
||||||
|
}
|
||||||
|
else if (propertyName == nameof(this.TaskBarPlacement) && this.taskBar != null)
|
||||||
|
{
|
||||||
|
this.RowDefinitions.Clear();
|
||||||
|
this.ColumnDefinitions.Clear();
|
||||||
|
switch ((TaskBarPlacement)newValue)
|
||||||
|
{
|
||||||
|
case TaskBarPlacement.Top:
|
||||||
|
this.RowDefinitions.Add(new RowDefinition { Height = 35 });
|
||||||
|
this.RowDefinitions.Add(new RowDefinition { Height = GridLength.Star });
|
||||||
|
RowIndex(this.taskBar, 0);
|
||||||
|
RowIndex(this.host, 1);
|
||||||
|
break;
|
||||||
|
case TaskBarPlacement.Bottom:
|
||||||
|
this.RowDefinitions.Add(new RowDefinition { Height = GridLength.Star });
|
||||||
|
this.RowDefinitions.Add(new RowDefinition { Height = 35 });
|
||||||
|
RowIndex(this.host, 0);
|
||||||
|
RowIndex(this.taskBar, 1);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.OnPropertyChanged(propertyName, oldValue, newValue, propertyMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Host_PropertyChanged(object sender, CPFPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.PropertyName.Or(nameof(ActualSize), nameof(Size), nameof(Width), nameof(Height)))
|
||||||
|
{
|
||||||
|
foreach (MdiWindow mdi in this.host.Children)
|
||||||
|
{
|
||||||
|
if (mdi.WindowState == WindowState.Maximized) continue;
|
||||||
|
|
||||||
|
if (mdi.MarginLeft.Value + mdi.ActualSize.Width > this.ActualSize.Width)
|
||||||
|
{
|
||||||
|
mdi.MarginLeft = this.ActualSize.Width - mdi.ActualSize.Width;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mdi.MarginTop.Value + mdi.ActualSize.Height > this.ActualSize.Height)
|
||||||
|
{
|
||||||
|
mdi.MarginTop = this.ActualSize.Height - mdi.ActualSize.Height;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Host_UIElementRemoved(object sender, UIElementRemovedEventArgs e)
|
||||||
|
{
|
||||||
|
var view = e.Element as MdiWindow;
|
||||||
|
view.PropertyChanged -= Element_PropertyChanged;
|
||||||
|
view.PreviewMouseDown -= Element_PreviewMouseDown;
|
||||||
|
view.Closing -= View_Closing;
|
||||||
|
this.TaskBarList.Remove(e.Element);
|
||||||
|
this.normalRect.Remove(e.Element);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Host_UIElementAdded(object sender, UIElementAddedEventArgs e)
|
||||||
|
{
|
||||||
|
var view = e.Element as MdiWindow;
|
||||||
|
this.normalRect.Add(e.Element, new MdiWindowRect { Left = 0, Top = 0, Height = 500, Width = 500 });
|
||||||
|
view.PropertyChanged += Element_PropertyChanged;
|
||||||
|
view.PreviewMouseDown += Element_PreviewMouseDown;
|
||||||
|
view.Closing += View_Closing;
|
||||||
|
this.TaskBarList.Add(view);
|
||||||
|
e.Element.ZIndex = this.host.Children.Max(x => x.ZIndex) + 1;
|
||||||
|
this.Topping(view);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void View_Closing(object sender, ClosingEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Cancel) return;
|
||||||
|
UIElement mdiWindow = null;
|
||||||
|
if (sender is IClosable closable)
|
||||||
|
{
|
||||||
|
mdiWindow = this.host.Children.FirstOrDefault(x => x.DataContext == closable);
|
||||||
|
}
|
||||||
|
else if (sender is MdiWindow mdi)
|
||||||
|
{
|
||||||
|
mdiWindow = mdi;
|
||||||
|
}
|
||||||
|
if (mdiWindow != null)
|
||||||
|
{
|
||||||
|
if (mdiWindow == this.SelectWindow)
|
||||||
|
{
|
||||||
|
this.BeginInvoke(() =>
|
||||||
|
{
|
||||||
|
if (this.host.Children.Count == 0) return;
|
||||||
|
var index = this.host.Children.Where(x => x.Visibility == Visibility.Visible).Max(x => x.ZIndex);
|
||||||
|
if (index != -1)
|
||||||
|
{
|
||||||
|
this.SelectWindow = this.host.Children.Find(x => x.ZIndex == index) as MdiWindow;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
this.host.Children.Remove(mdiWindow);
|
||||||
|
mdiWindow.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Element_PreviewMouseDown(object sender, Input.MouseButtonEventArgs e)
|
||||||
|
{
|
||||||
|
var ele = (MdiWindow)sender;
|
||||||
|
this.Topping(ele);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Element_PropertyChanged(object sender, CPFPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
var view = sender as MdiWindow;
|
||||||
|
switch (e.PropertyName)
|
||||||
|
{
|
||||||
|
case nameof(MdiWindow.WindowState):
|
||||||
|
|
||||||
|
switch ((WindowState)e.NewValue)
|
||||||
|
{
|
||||||
|
case WindowState.Normal:
|
||||||
|
var rect = this.normalRect[view];
|
||||||
|
view.Size = new SizeField(rect.Width, rect.Height);
|
||||||
|
view.MarginLeft = rect.Left;
|
||||||
|
view.MarginTop = rect.Top;
|
||||||
|
break;
|
||||||
|
case WindowState.Minimized:
|
||||||
|
view.Visibility = Visibility.Collapsed;
|
||||||
|
this.SelectWindow = this.host.Children.FindLast(x => x.Visibility == Visibility.Visible) as MdiWindow;
|
||||||
|
this.normalRect[view].OldState = (WindowState)e.OldValue;
|
||||||
|
break;
|
||||||
|
case WindowState.Maximized:
|
||||||
|
case WindowState.FullScreen:
|
||||||
|
view.Size = SizeField.Fill;
|
||||||
|
view.MarginLeft = 0;
|
||||||
|
view.MarginTop = 0;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(ZIndex):
|
||||||
|
this.SelectWindow = view;
|
||||||
|
this.SelectWindow.Visibility = Visibility.Visible;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(MarginLeft):
|
||||||
|
if (view.WindowState == WindowState.Normal)
|
||||||
|
{
|
||||||
|
var left = (FloatField)e.NewValue;
|
||||||
|
if (left.Value <= 0) view.MarginLeft = 0;
|
||||||
|
this.normalRect[view].Left = view.MarginLeft.Value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case nameof(MarginTop):
|
||||||
|
if (view.WindowState == WindowState.Normal)
|
||||||
|
{
|
||||||
|
var top = (FloatField)e.NewValue;
|
||||||
|
if (top.Value <= 0) view.MarginTop = 0;
|
||||||
|
this.normalRect[view].Top = view.MarginTop.Value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(Width):
|
||||||
|
if (view.WindowState == WindowState.Normal)
|
||||||
|
{
|
||||||
|
var size = (FloatField)e.NewValue;
|
||||||
|
this.normalRect[view].Width = size.Value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(Height):
|
||||||
|
if (view.WindowState == WindowState.Normal)
|
||||||
|
{
|
||||||
|
var size = (FloatField)e.NewValue;
|
||||||
|
this.normalRect[view].Height = size.Value;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Topping(MdiWindow ele)
|
||||||
|
{
|
||||||
|
if (ele == null) return;
|
||||||
|
ele.Focus();
|
||||||
|
var index = this.host.Children.Max(x => x.ZIndex);
|
||||||
|
if (ele.ZIndex == index)
|
||||||
|
{
|
||||||
|
ele.Visibility = Visibility.Visible;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
ele.ZIndex = index + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
class TaskBarItem : ListBoxItem
|
||||||
|
{
|
||||||
|
public event EventHandler CloseClick
|
||||||
|
{
|
||||||
|
add { AddHandler(value); }
|
||||||
|
remove { RemoveHandler(value); }
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.Size = new SizeField(100, "90%");
|
||||||
|
this.Background = "white";
|
||||||
|
this.BorderFill = "gray";
|
||||||
|
this.BorderStroke = "1";
|
||||||
|
this.CornerRadius = new CornerRadius(2);
|
||||||
|
this.Margin = new ThicknessField(1);
|
||||||
|
this.IsAntiAlias = true;
|
||||||
|
this.UseLayoutRounding = true;
|
||||||
|
this.CommandContext = this;
|
||||||
|
this.Triggers.Add(new Trigger
|
||||||
|
{
|
||||||
|
Property = nameof(IsSelected),
|
||||||
|
Setters =
|
||||||
|
{
|
||||||
|
{ nameof(Background),nameof(Color.DodgerBlue) },
|
||||||
|
{ nameof(Foreground),"white" }
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.Children.Add(new Grid
|
||||||
|
{
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
ColumnDefinitions =
|
||||||
|
{
|
||||||
|
new ColumnDefinition{ },
|
||||||
|
new ColumnDefinition{ Width = 30 },
|
||||||
|
},
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new TextBlock
|
||||||
|
{
|
||||||
|
Height = "auto",
|
||||||
|
TextTrimming = TextTrimming.CharacterEllipsis,
|
||||||
|
TextAlignment = TextAlignment.Center,
|
||||||
|
[nameof(TextBlock.Text)] = new BindingDescribe("Title"),
|
||||||
|
},
|
||||||
|
new Panel
|
||||||
|
{
|
||||||
|
Name = "close",
|
||||||
|
Attacheds = { { Grid.ColumnIndex,1 } },
|
||||||
|
MarginRight = 5,
|
||||||
|
Size = new SizeField(15,15),
|
||||||
|
CornerRadius = new CornerRadius(5),
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new Line
|
||||||
|
{
|
||||||
|
MarginLeft = 2,
|
||||||
|
MarginTop = 2,
|
||||||
|
StartPoint = new Point(1, 1),
|
||||||
|
EndPoint = new Point(10, 10),
|
||||||
|
StrokeStyle = "2",
|
||||||
|
IsAntiAlias = true,
|
||||||
|
[nameof(Line.StrokeFill)] = new BindingDescribe(this,nameof(Foreground)),
|
||||||
|
},
|
||||||
|
new Line
|
||||||
|
{
|
||||||
|
MarginLeft = 2,
|
||||||
|
MarginTop = 2,
|
||||||
|
StartPoint = new Point(10, 1),
|
||||||
|
EndPoint = new Point(1, 10),
|
||||||
|
StrokeStyle = "2",
|
||||||
|
IsAntiAlias = true,
|
||||||
|
[nameof(Line.StrokeFill)] = new BindingDescribe(this,nameof(Foreground)),
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Triggers =
|
||||||
|
{
|
||||||
|
new Trigger
|
||||||
|
{
|
||||||
|
Property = nameof(IsMouseOver),
|
||||||
|
Setters =
|
||||||
|
{
|
||||||
|
{ nameof(Background) ,"red" },
|
||||||
|
{ nameof(Foreground) ,"white" },
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[nameof(Panel.MouseUp)] = new CommandDescribe((s,e) => this.RaiseEvent(e,nameof(this.CloseClick)))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
class MdiWindowRect
|
||||||
|
{
|
||||||
|
public MdiWindowRect()
|
||||||
|
{
|
||||||
|
|
||||||
|
}
|
||||||
|
public MdiWindowRect(float left, float top, float width, float height)
|
||||||
|
{
|
||||||
|
this.Left = left;
|
||||||
|
this.Top = top;
|
||||||
|
this.Width = width;
|
||||||
|
this.Height = height;
|
||||||
|
}
|
||||||
|
public float Left { get; set; }
|
||||||
|
public float Top { get; set; }
|
||||||
|
public float Width { get; set; }
|
||||||
|
public float Height { get; set; }
|
||||||
|
|
||||||
|
public WindowState OldState { get; set; }
|
||||||
|
|
||||||
|
public override string ToString()
|
||||||
|
{
|
||||||
|
return $"left:{this.Left} top:{this.Top} width:{this.Width} height:{this.Height}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public enum TaskBarPlacement
|
||||||
|
{
|
||||||
|
Top,
|
||||||
|
Bottom,
|
||||||
|
}
|
||||||
|
}
|
488
CPF.Toolkit/Controls/MdiWindow.cs
Normal file
488
CPF.Toolkit/Controls/MdiWindow.cs
Normal file
@ -0,0 +1,488 @@
|
|||||||
|
using CPF;
|
||||||
|
using CPF.Animation;
|
||||||
|
using CPF.Charts;
|
||||||
|
using CPF.Controls;
|
||||||
|
using CPF.Drawing;
|
||||||
|
using CPF.Input;
|
||||||
|
using CPF.Platform;
|
||||||
|
using CPF.Shapes;
|
||||||
|
using CPF.Styling;
|
||||||
|
using CPF.Svg;
|
||||||
|
using CPF.Toolkit.Dialogs;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Reflection;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit.Controls
|
||||||
|
{
|
||||||
|
public class MdiWindow : Control
|
||||||
|
{
|
||||||
|
public MdiWindow()
|
||||||
|
{
|
||||||
|
this.Init();
|
||||||
|
}
|
||||||
|
public WindowState WindowState { get => GetValue<WindowState>(); set => SetValue(value); }
|
||||||
|
public UIElement Content { get => GetValue<UIElement>(); set => SetValue(value); }
|
||||||
|
|
||||||
|
[PropertyMetadata("Title")]
|
||||||
|
public string Title { get => GetValue<string>(); set => SetValue(value); }
|
||||||
|
|
||||||
|
[PropertyMetadata(true)]
|
||||||
|
public bool MaximizeBox { get { return GetValue<bool>(); } set { SetValue(value); } }
|
||||||
|
|
||||||
|
[PropertyMetadata(true)]
|
||||||
|
public bool MinimizeBox { get { return GetValue<bool>(); } set { SetValue(value); } }
|
||||||
|
|
||||||
|
[PropertyMetadata(true)]
|
||||||
|
public bool CloseBox { get { return GetValue<bool>(); } set { SetValue(value); } }
|
||||||
|
|
||||||
|
[UIPropertyMetadata((byte)5, UIPropertyOptions.AffectsMeasure)]
|
||||||
|
public byte ShadowBlur { get { return GetValue<byte>(); } set { SetValue(value); } }
|
||||||
|
|
||||||
|
[PropertyMetadata(true)]
|
||||||
|
public bool CanResize
|
||||||
|
{
|
||||||
|
get => GetValue<bool>();
|
||||||
|
set
|
||||||
|
{
|
||||||
|
SetValue(value);
|
||||||
|
if (!value) this.MaximizeBox = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public event EventHandler<ClosingEventArgs> Closing;
|
||||||
|
|
||||||
|
|
||||||
|
void Init()
|
||||||
|
{
|
||||||
|
this.Focusable = true;
|
||||||
|
var borderColor = (ViewFill)"152,180,208";
|
||||||
|
var lostFocusBorderColor = (ViewFill)"214,227,241";
|
||||||
|
var dragEnabled = new BindingDescribe(this, nameof(WindowState), BindingMode.OneWay, x =>
|
||||||
|
{
|
||||||
|
if (this.CanResize)
|
||||||
|
{
|
||||||
|
return ((WindowState)x) == WindowState.Normal;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
});
|
||||||
|
this.Size = new SizeField(500, 500);
|
||||||
|
this.Background = null;
|
||||||
|
this.MarginLeft = 0;
|
||||||
|
this.MarginTop = 0;
|
||||||
|
this.ClipToBounds = true;
|
||||||
|
this.Children.Add(new Border
|
||||||
|
{
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Background = "white",
|
||||||
|
BorderType = BorderType.BorderStroke,
|
||||||
|
BorderStroke = "0",
|
||||||
|
//ShadowBlur = ShadowBlur,
|
||||||
|
ShadowColor = Color.FromRgba(0, 0, 0, 150),
|
||||||
|
Child = new Decorator
|
||||||
|
{
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
ClipToBounds = true,
|
||||||
|
Child = new Grid
|
||||||
|
{
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
ColumnDefinitions =
|
||||||
|
{
|
||||||
|
new ColumnDefinition{ Width = "auto" },
|
||||||
|
new ColumnDefinition{ },
|
||||||
|
new ColumnDefinition{ Width = "auto" },
|
||||||
|
},
|
||||||
|
RowDefinitions =
|
||||||
|
{
|
||||||
|
new RowDefinition{ Height = "auto" },
|
||||||
|
new RowDefinition{ Height = 30 },
|
||||||
|
new RowDefinition{ },
|
||||||
|
new RowDefinition{ Height = "auto" },
|
||||||
|
},
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new Thumb
|
||||||
|
{
|
||||||
|
Name = "top",
|
||||||
|
Size = "100%,5",
|
||||||
|
Cursor = Cursors.SizeNorthSouth,
|
||||||
|
Attacheds = { { Grid.ColumnIndex,1 } },
|
||||||
|
[nameof(IsEnabled)] = dragEnabled,
|
||||||
|
[nameof(Background)] = new BindingDescribe(this,nameof(IsFocused),BindingMode.OneWay ,x => ((bool)x) ? borderColor : lostFocusBorderColor),
|
||||||
|
[nameof(Thumb.DragDelta)] = new CommandDescribe((s,e) =>
|
||||||
|
{
|
||||||
|
var args = e as DragDeltaEventArgs;
|
||||||
|
if (this.Height.Value - args.VerticalChange > 0)
|
||||||
|
{
|
||||||
|
this.MarginTop += args.VerticalChange;
|
||||||
|
this.Height -= args.VerticalChange;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
new Thumb
|
||||||
|
{
|
||||||
|
Name = "left",
|
||||||
|
Size = "5,100%",
|
||||||
|
Cursor = Cursors.SizeWestEast,
|
||||||
|
Attacheds = { { Grid.RowIndex,1 },{ Grid.RowSpan,2 } },
|
||||||
|
[nameof(IsEnabled)] = dragEnabled,
|
||||||
|
[nameof(Background)] = new BindingDescribe(this,nameof(IsFocused),BindingMode.OneWay ,x => ((bool)x) ? borderColor : lostFocusBorderColor),
|
||||||
|
[nameof(Thumb.DragDelta)] = new CommandDescribe((s,e) =>
|
||||||
|
{
|
||||||
|
var args = e as DragDeltaEventArgs;
|
||||||
|
if (this.Width.Value - args.HorizontalChange > 0)
|
||||||
|
{
|
||||||
|
this.MarginLeft += args.HorizontalChange;
|
||||||
|
this.Width -= args.HorizontalChange;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
new Thumb
|
||||||
|
{
|
||||||
|
Name = "left_top",
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Cursor = Cursors.TopLeftCorner,
|
||||||
|
[nameof(IsEnabled)] = dragEnabled,
|
||||||
|
[nameof(Background)] = new BindingDescribe(this,nameof(IsFocused),BindingMode.OneWay ,x => ((bool)x) ? borderColor : lostFocusBorderColor),
|
||||||
|
[nameof(Thumb.DragDelta)] = new CommandDescribe((s,e) =>
|
||||||
|
{
|
||||||
|
var args = e as DragDeltaEventArgs;
|
||||||
|
if (this.Width.Value - args.HorizontalChange > 0 && this.Height.Value - args.VerticalChange > 0)
|
||||||
|
{
|
||||||
|
this.MarginLeft += args.HorizontalChange;
|
||||||
|
this.MarginTop += args.VerticalChange;
|
||||||
|
this.Width -= args.HorizontalChange;
|
||||||
|
this.Height -= args.VerticalChange;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
new Thumb
|
||||||
|
{
|
||||||
|
Name = "right",
|
||||||
|
Size = "5,100%",
|
||||||
|
Cursor = Cursors.SizeWestEast,
|
||||||
|
MarginRight = 0,
|
||||||
|
Attacheds = { { Grid.ColumnIndex,2 },{ Grid.RowIndex,1 },{ Grid.RowSpan,2 } },
|
||||||
|
[nameof(IsEnabled)] = dragEnabled,
|
||||||
|
[nameof(Thumb.DragDelta)] = new CommandDescribe((s,e) => this.Width += (e as DragDeltaEventArgs).HorizontalChange),
|
||||||
|
[nameof(Background)] = new BindingDescribe(this,nameof(IsFocused),BindingMode.OneWay ,x => ((bool)x) ? borderColor : lostFocusBorderColor),
|
||||||
|
},
|
||||||
|
new Thumb
|
||||||
|
{
|
||||||
|
Name = "right_top",
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Cursor = Cursors.TopRightCorner,
|
||||||
|
MarginRight = 0,
|
||||||
|
Attacheds = { { Grid.ColumnIndex,2 } },
|
||||||
|
[nameof(IsEnabled)] = dragEnabled,
|
||||||
|
[nameof(Background)] = new BindingDescribe(this,nameof(IsFocused),BindingMode.OneWay ,x => ((bool)x) ? borderColor : lostFocusBorderColor),
|
||||||
|
[nameof(Thumb.DragDelta)] = new CommandDescribe((s,e) =>
|
||||||
|
{
|
||||||
|
var args = e as DragDeltaEventArgs;
|
||||||
|
if (this.Width.Value - args.HorizontalChange > 0 && this.Height.Value - args.VerticalChange > 0)
|
||||||
|
{
|
||||||
|
this.MarginTop += args.VerticalChange;
|
||||||
|
this.Width += args.HorizontalChange;
|
||||||
|
this.Height -= args.VerticalChange;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
new Thumb
|
||||||
|
{
|
||||||
|
Name = "bottom",
|
||||||
|
Size = "100%,5",
|
||||||
|
Cursor = Cursors.SizeNorthSouth,
|
||||||
|
Attacheds = { { Grid.RowIndex,3 },{ Grid.ColumnIndex,1 } },
|
||||||
|
[nameof(IsEnabled)] = dragEnabled,
|
||||||
|
[nameof(Thumb.DragDelta)] = new CommandDescribe((s,e) => this.Height += (e as DragDeltaEventArgs).VerticalChange),
|
||||||
|
[nameof(Background)] = new BindingDescribe(this,nameof(IsFocused),BindingMode.OneWay ,x => ((bool)x) ? borderColor : lostFocusBorderColor),
|
||||||
|
},
|
||||||
|
new Thumb
|
||||||
|
{
|
||||||
|
Name = "left_bottom",
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Cursor = Cursors.BottomLeftCorner,
|
||||||
|
Attacheds = { { Grid.RowIndex,3 } },
|
||||||
|
[nameof(Background)] = new BindingDescribe(this,nameof(IsFocused),BindingMode.OneWay ,x => ((bool)x) ? borderColor : lostFocusBorderColor),
|
||||||
|
[nameof(IsEnabled)] = dragEnabled,
|
||||||
|
[nameof(Thumb.DragDelta)] = new CommandDescribe((s,e) =>
|
||||||
|
{
|
||||||
|
var args = e as DragDeltaEventArgs;
|
||||||
|
if (this.Width.Value - args.HorizontalChange > 0 && this.Height.Value + args.VerticalChange > 0)
|
||||||
|
{
|
||||||
|
this.MarginLeft += args.HorizontalChange;
|
||||||
|
this.Width -= args.HorizontalChange;
|
||||||
|
this.Height += args.VerticalChange;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
new Thumb
|
||||||
|
{
|
||||||
|
Name = "right_bottom",
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Cursor = Cursors.BottomRightCorner,
|
||||||
|
Attacheds = { { Grid.RowIndex,3 },{ Grid.ColumnIndex,2 } },
|
||||||
|
[nameof(Background)] = new BindingDescribe(this,nameof(IsFocused),BindingMode.OneWay ,x => ((bool)x) ? borderColor : lostFocusBorderColor),
|
||||||
|
[nameof(IsEnabled)] = dragEnabled,
|
||||||
|
[nameof(Thumb.DragDelta)] = new CommandDescribe((s,e) =>
|
||||||
|
{
|
||||||
|
var args = e as DragDeltaEventArgs;
|
||||||
|
if (this.Height.Value + args.VerticalChange > 0 && this.Width.Value + args.HorizontalChange > 0)
|
||||||
|
{
|
||||||
|
this.Width += args.HorizontalChange;
|
||||||
|
this.Height += args.VerticalChange;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
new Thumb
|
||||||
|
{
|
||||||
|
Name = "caption",
|
||||||
|
Attacheds = { { Grid.RowIndex,1 },{ Grid.ColumnIndex,1 } },
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Child = new Panel
|
||||||
|
{
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new StackPanel
|
||||||
|
{
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
|
MarginLeft = 0,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new TextBlock
|
||||||
|
{
|
||||||
|
[nameof(TextBlock.Text)] = new BindingDescribe(this,nameof(this.Title),BindingMode.OneWay),
|
||||||
|
FontSize = 14,
|
||||||
|
MarginLeft = 10,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new StackPanel
|
||||||
|
{
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
|
MarginRight = 0,
|
||||||
|
Height = "100%",
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new SystemButton
|
||||||
|
{
|
||||||
|
Name = "min",
|
||||||
|
Size = new SizeField(30,"100%"),
|
||||||
|
Content = new Line
|
||||||
|
{
|
||||||
|
MarginLeft = "auto",
|
||||||
|
StartPoint = new Point(1,13),
|
||||||
|
EndPoint = new Point(14,13),
|
||||||
|
StrokeStyle = "2",
|
||||||
|
IsAntiAlias = true,
|
||||||
|
StrokeFill = "black"
|
||||||
|
},
|
||||||
|
[nameof(Visibility)] = new BindingDescribe(this,nameof(MinimizeBox),BindingMode.OneWay,x=>(bool)x?Visibility.Visible: Visibility.Collapsed),
|
||||||
|
[nameof(Button.Click)] = new CommandDescribe((s,e) => this.WindowState = WindowState.Minimized)
|
||||||
|
},
|
||||||
|
new Panel
|
||||||
|
{
|
||||||
|
Height = "100%",
|
||||||
|
[nameof(Visibility)] = new BindingDescribe(this,nameof(MaximizeBox),BindingMode.OneWay,a => (bool)a ? Visibility.Visible : Visibility.Collapsed),
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new SystemButton
|
||||||
|
{
|
||||||
|
Name = "max",
|
||||||
|
Size = new SizeField(30,"100%"),
|
||||||
|
Content = new Rectangle
|
||||||
|
{
|
||||||
|
Size = new SizeField(14,12),
|
||||||
|
MarginTop = 5,
|
||||||
|
StrokeStyle = "2",
|
||||||
|
},
|
||||||
|
[nameof(Button.Click)] = new CommandDescribe((s, e) => this.WindowState = WindowState.Maximized),
|
||||||
|
[nameof(Visibility)] =
|
||||||
|
new BindingDescribe(
|
||||||
|
this,
|
||||||
|
nameof(WindowState),
|
||||||
|
BindingMode.OneWay,
|
||||||
|
x => ((WindowState)x).Or(WindowState.Maximized,WindowState.FullScreen) ? Visibility.Collapsed : Visibility.Visible),
|
||||||
|
},
|
||||||
|
new SystemButton
|
||||||
|
{
|
||||||
|
Name = "nor",
|
||||||
|
Visibility = Visibility.Collapsed,
|
||||||
|
Size = new SizeField(30,"100%"),
|
||||||
|
Content = new Panel
|
||||||
|
{
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new Rectangle
|
||||||
|
{
|
||||||
|
MarginTop = 10,
|
||||||
|
MarginLeft =8,
|
||||||
|
Size = new SizeField(11,8),
|
||||||
|
StrokeStyle = "1.5",
|
||||||
|
},
|
||||||
|
new Polyline
|
||||||
|
{
|
||||||
|
MarginTop =5,
|
||||||
|
MarginLeft = 12,
|
||||||
|
Points =
|
||||||
|
{
|
||||||
|
new Point(0,3),
|
||||||
|
new Point(0,0),
|
||||||
|
new Point(9,0),
|
||||||
|
new Point(9,7),
|
||||||
|
new Point(6,7)
|
||||||
|
},
|
||||||
|
StrokeStyle = "2"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[nameof(Button.Click)] = new CommandDescribe((s, e) => this.WindowState = WindowState.Normal),
|
||||||
|
[nameof(Visibility)] =
|
||||||
|
new BindingDescribe(
|
||||||
|
this,
|
||||||
|
nameof(WindowState),
|
||||||
|
BindingMode.OneWay,
|
||||||
|
x => ((WindowState)x).Or(WindowState.Normal,WindowState.Minimized)? Visibility.Collapsed : Visibility.Visible)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new SystemButton
|
||||||
|
{
|
||||||
|
Name = "close",
|
||||||
|
Size = new SizeField(30,"100%"),
|
||||||
|
Content = new Panel
|
||||||
|
{
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new Line
|
||||||
|
{
|
||||||
|
MarginTop=4,
|
||||||
|
MarginLeft=8,
|
||||||
|
StartPoint = new Point(1, 1),
|
||||||
|
EndPoint = new Point(14, 13),
|
||||||
|
StrokeStyle = "2",
|
||||||
|
IsAntiAlias=true,
|
||||||
|
},
|
||||||
|
new Line
|
||||||
|
{
|
||||||
|
MarginTop=4,
|
||||||
|
MarginLeft=8,
|
||||||
|
StartPoint = new Point(14, 1),
|
||||||
|
EndPoint = new Point(1, 13),
|
||||||
|
StrokeStyle = "2",
|
||||||
|
IsAntiAlias=true,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
[nameof(Button.Click)] = new CommandDescribe((ss,ee) => this.Close()),
|
||||||
|
[nameof(Visibility)] = new BindingDescribe(this,nameof(this.CloseBox),BindingMode.OneWay,x=>(bool)x?Visibility.Visible: Visibility.Collapsed)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[nameof(Thumb.DragDelta)] = new CommandDescribe((ss,ee)=>
|
||||||
|
{
|
||||||
|
if (this.WindowState.Or(WindowState.Normal))
|
||||||
|
{
|
||||||
|
var arge = ee as DragDeltaEventArgs;
|
||||||
|
this.MarginLeft += arge.HorizontalChange;
|
||||||
|
this.MarginTop += arge.VerticalChange;
|
||||||
|
}
|
||||||
|
}),
|
||||||
|
[nameof(DoubleClick)] = new CommandDescribe((ss,ee) => this.Delay(TimeSpan.FromMilliseconds(150),()=>
|
||||||
|
{
|
||||||
|
if(!this.MaximizeBox) return;
|
||||||
|
if (this.WindowState.Or(WindowState.Maximized,WindowState.Minimized))
|
||||||
|
{
|
||||||
|
this.WindowState = WindowState.Normal;
|
||||||
|
}
|
||||||
|
else if (this.WindowState == WindowState.Normal)
|
||||||
|
{
|
||||||
|
this.WindowState = WindowState.Maximized;
|
||||||
|
}
|
||||||
|
})),
|
||||||
|
[nameof(Background)] = new BindingDescribe(this,nameof(IsFocused),BindingMode.OneWay ,x => ((bool)x) ? borderColor : lostFocusBorderColor)
|
||||||
|
},
|
||||||
|
new Decorator
|
||||||
|
{
|
||||||
|
Attacheds = { { Grid.RowIndex,2 } ,{ Grid.ColumnIndex,1 } },
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
[nameof(Decorator.Child)] = new BindingDescribe(this,nameof(Content))
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
[nameof(ShadowBlur)] = new BindingDescribe(this, nameof(WindowState), BindingMode.OneWay, x => ((WindowState)x).Or(WindowState.Maximized, WindowState.FullScreen) ? 0 : ShadowBlur),
|
||||||
|
Triggers =
|
||||||
|
{
|
||||||
|
new Trigger
|
||||||
|
{
|
||||||
|
Property = nameof(IsFocused),
|
||||||
|
Setters =
|
||||||
|
{
|
||||||
|
{ nameof(ShadowBlur),ShadowBlur },
|
||||||
|
{ nameof(BorderStroke),"1" },
|
||||||
|
{ nameof(BorderFill),"0,0,0,100" },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue, PropertyMetadataAttribute propertyMetadata)
|
||||||
|
{
|
||||||
|
if (propertyName == nameof(DataContext) && newValue != null)
|
||||||
|
{
|
||||||
|
if (newValue is IClosable closable)
|
||||||
|
{
|
||||||
|
closable.Closable -= Closable_Closable;
|
||||||
|
closable.Closable += Closable_Closable;
|
||||||
|
}
|
||||||
|
if (newValue is ILoading loading)
|
||||||
|
{
|
||||||
|
loading.CreateLoading(this);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (propertyName == nameof(Content) && newValue != null)
|
||||||
|
{
|
||||||
|
this.Content.Margin = "0";
|
||||||
|
this.Content.ClipToBounds = true;
|
||||||
|
}
|
||||||
|
base.OnPropertyChanged(propertyName, oldValue, newValue, propertyMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Closable_Closable(object sender, ClosingEventArgs e)
|
||||||
|
{
|
||||||
|
this.DoClose(sender, e);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Close()
|
||||||
|
{
|
||||||
|
if (this.Closing != null)
|
||||||
|
{
|
||||||
|
this.DoClose(this, new ClosingEventArgs());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
this.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void DoClose(object sender, ClosingEventArgs e)
|
||||||
|
{
|
||||||
|
if (this.DataContext is IClosable closable)
|
||||||
|
{
|
||||||
|
closable.OnClosable(sender, e);
|
||||||
|
}
|
||||||
|
this.Closing.Invoke(sender, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
230
CPF.Toolkit/Controls/PageControl.cs
Normal file
230
CPF.Toolkit/Controls/PageControl.cs
Normal file
@ -0,0 +1,230 @@
|
|||||||
|
using CPF;
|
||||||
|
using CPF.Animation;
|
||||||
|
using CPF.Charts;
|
||||||
|
using CPF.Controls;
|
||||||
|
using CPF.Drawing;
|
||||||
|
using CPF.Input;
|
||||||
|
using CPF.Shapes;
|
||||||
|
using CPF.Styling;
|
||||||
|
using CPF.Svg;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Collections.ObjectModel;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit.Controls
|
||||||
|
{
|
||||||
|
public class PageControl : Control
|
||||||
|
{
|
||||||
|
public PageControl()
|
||||||
|
{
|
||||||
|
this.Pages = new ObservableCollection<int>();
|
||||||
|
}
|
||||||
|
public int PageIndex { get => GetValue<int>(); set => SetValue(value); }
|
||||||
|
public int PageCount { get => GetValue<int>(); set => SetValue(value); }
|
||||||
|
int pageSize = 10;
|
||||||
|
|
||||||
|
public event EventHandler<IndexEventArgs> PageIndexChanged { add => AddHandler(value); remove => RemoveHandler(value); }
|
||||||
|
|
||||||
|
ObservableCollection<int> Pages { get => GetValue<ObservableCollection<int>>(); set => SetValue(value); }
|
||||||
|
|
||||||
|
protected override void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.Size = SizeField.Fill;
|
||||||
|
this.Children.Add(new StackPanel
|
||||||
|
{
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "上一页",
|
||||||
|
[nameof(IsEnabled)] = new BindingDescribe(this,nameof(this.PageIndex),BindingMode.OneWay,c => ((int)c) > 1),
|
||||||
|
},
|
||||||
|
new ListBox
|
||||||
|
{
|
||||||
|
ItemTemplate = new PageButton
|
||||||
|
{
|
||||||
|
[nameof(PageIndexChanged)] = new CommandDescribe((s,e) => this.PageIndex = (e as IndexEventArgs).Index)
|
||||||
|
},
|
||||||
|
ItemsPanel = new StackPanel{Orientation = Orientation.Horizontal,},
|
||||||
|
Items = this.Pages,
|
||||||
|
},
|
||||||
|
new TextBlock
|
||||||
|
{
|
||||||
|
Text = "……",
|
||||||
|
[nameof(Visibility)] = new BindingDescribe(this,nameof(this.PageCount),BindingMode.OneWay,c => ((int)c) > this.pageSize ? Visibility.Visible : Visibility.Collapsed)
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "100",
|
||||||
|
[nameof(Visibility)] = new BindingDescribe(this,nameof(this.PageCount),BindingMode.OneWay,c => ((int)c) > this.pageSize ? Visibility.Visible : Visibility.Collapsed)
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "下一页",
|
||||||
|
[nameof(IsEnabled)] = new BindingDescribe(this,nameof(this.PageIndex),BindingMode.OneWay,c => ((int)c) < this.PageCount),
|
||||||
|
},
|
||||||
|
new StackPanel
|
||||||
|
{
|
||||||
|
MarginLeft = 10,
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new TextBlock
|
||||||
|
{
|
||||||
|
Text = "1 ",
|
||||||
|
Foreground = "dodgerblue",
|
||||||
|
},
|
||||||
|
new TextBlock
|
||||||
|
{
|
||||||
|
Text = $"/ 100",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new TextBlock
|
||||||
|
{
|
||||||
|
Text = " 到第几 "
|
||||||
|
},
|
||||||
|
new Border
|
||||||
|
{
|
||||||
|
MinHeight = 35,
|
||||||
|
MinWidth = 35,
|
||||||
|
MarginLeft = 2,
|
||||||
|
MarginRight = 2,
|
||||||
|
Child = new TextBox
|
||||||
|
{
|
||||||
|
Width = "100%",
|
||||||
|
Text = "10",
|
||||||
|
TextAlignment = TextAlignment.Center,
|
||||||
|
FontSize = 14,
|
||||||
|
},
|
||||||
|
BorderFill = "silver",
|
||||||
|
BorderStroke = "1",
|
||||||
|
CornerRadius = new CornerRadius(2),
|
||||||
|
IsAntiAlias = true,
|
||||||
|
UseLayoutRounding = true,
|
||||||
|
},
|
||||||
|
new TextBlock
|
||||||
|
{
|
||||||
|
Text = " 页 " ,
|
||||||
|
},
|
||||||
|
new Button
|
||||||
|
{
|
||||||
|
Content = "确定",
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
foreach (var item in this.Find<TextBlock>())
|
||||||
|
{
|
||||||
|
item.FontSize = 14;
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var item in Find<Button>())
|
||||||
|
{
|
||||||
|
item.BorderFill = "dodgerblue";
|
||||||
|
item.BorderStroke = "1";
|
||||||
|
item.CornerRadius = new CornerRadius(4);
|
||||||
|
item.Background = "white";
|
||||||
|
item.Foreground = "dodgerblue";
|
||||||
|
item.MinWidth = 35;
|
||||||
|
item.MinHeight = 35;
|
||||||
|
item.MarginRight = 2;
|
||||||
|
item.IsAntiAlias = true;
|
||||||
|
item.UseLayoutRounding = true;
|
||||||
|
if (!int.TryParse(item.Content.ToString(), out var _))
|
||||||
|
{
|
||||||
|
item.Width = 60;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue, PropertyMetadataAttribute propertyMetadata)
|
||||||
|
{
|
||||||
|
if (propertyName.Or(nameof(this.PageIndex), nameof(this.PageCount)))
|
||||||
|
{
|
||||||
|
this.Pages.Clear();
|
||||||
|
for (int i = 1; i <= this.PageCount; i++)
|
||||||
|
{
|
||||||
|
if (i > this.pageSize)
|
||||||
|
{
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
this.Pages.Add(i);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
base.OnPropertyChanged(propertyName, oldValue, newValue, propertyMetadata);
|
||||||
|
}
|
||||||
|
|
||||||
|
class PageButton : ListBoxItem
|
||||||
|
{
|
||||||
|
public event EventHandler<IndexEventArgs> PageIndexChanged { add => AddHandler(value); remove => RemoveHandler(value); }
|
||||||
|
|
||||||
|
protected override void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.Children.Add(new RadioButton
|
||||||
|
{
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
GroupName = "pageNumber",
|
||||||
|
Template = (ss, ee) =>
|
||||||
|
{
|
||||||
|
var s = ss as RadioButton;
|
||||||
|
s.BorderFill = "dodgerblue";
|
||||||
|
s.BorderStroke = "1";
|
||||||
|
s.CornerRadius = new CornerRadius(4);
|
||||||
|
s.Size = new SizeField(35, 35);
|
||||||
|
s.MarginLeft = 2;
|
||||||
|
s.MarginRight = 2;
|
||||||
|
s.UseLayoutRounding = true;
|
||||||
|
s.IsAntiAlias = true;
|
||||||
|
s.Foreground = "dodgerblue";
|
||||||
|
s.Cursor = Cursors.Hand;
|
||||||
|
ee.Add(new TextBlock
|
||||||
|
{
|
||||||
|
FontSize = 14,
|
||||||
|
[nameof(TextBlock.Text)] = new BindingDescribe(this, nameof(Content)),
|
||||||
|
});
|
||||||
|
s.Triggers.Add(new Trigger
|
||||||
|
{
|
||||||
|
Property = nameof(RadioButton.IsChecked),
|
||||||
|
PropertyConditions = (x) => (bool?)x == true,
|
||||||
|
Setters =
|
||||||
|
{
|
||||||
|
{ nameof(Background) , "dodgerblue" },
|
||||||
|
{ nameof(Foreground) , "white" },
|
||||||
|
},
|
||||||
|
});
|
||||||
|
},
|
||||||
|
[nameof(Content)] = new BindingDescribe(this, nameof(Content)),
|
||||||
|
[nameof(RadioButton.IsChecked)] = new BindingDescribe(new CommandDescribe((s, e) =>
|
||||||
|
{
|
||||||
|
var btn = s as RadioButton;
|
||||||
|
if (btn.IsChecked == true) this.RaiseEvent(new IndexEventArgs(Convert.ToInt32(btn.Content)), nameof(this.PageIndexChanged));
|
||||||
|
})),
|
||||||
|
}.Assign(out var rad));
|
||||||
|
|
||||||
|
//rad.PropertyChanged += Rad_PropertyChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Rad_PropertyChanged(object sender, CPFPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.PropertyName == "IsChecked" && ((bool?)e.NewValue) == true)
|
||||||
|
{
|
||||||
|
this.RaiseEvent(new IndexEventArgs(Convert.ToInt32((sender as RadioButton).Content)), nameof(this.PageIndexChanged));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
public class IndexEventArgs : EventArgs
|
||||||
|
{
|
||||||
|
public IndexEventArgs(int index)
|
||||||
|
{
|
||||||
|
this.Index = index;
|
||||||
|
}
|
||||||
|
public int Index { get; set; }
|
||||||
|
}
|
||||||
|
}
|
156
CPF.Toolkit/Dialogs/DialogView.cs
Normal file
156
CPF.Toolkit/Dialogs/DialogView.cs
Normal file
@ -0,0 +1,156 @@
|
|||||||
|
using CPF;
|
||||||
|
using CPF.Animation;
|
||||||
|
using CPF.Charts;
|
||||||
|
using CPF.Controls;
|
||||||
|
using CPF.Drawing;
|
||||||
|
using CPF.Input;
|
||||||
|
using CPF.Shapes;
|
||||||
|
using CPF.Styling;
|
||||||
|
using CPF.Svg;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Security.Cryptography;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit.Dialogs
|
||||||
|
{
|
||||||
|
internal class DialogView : Window
|
||||||
|
{
|
||||||
|
public DialogView(string text, string title, DialogType dialogType, string defaultButton, params string[] buttons)
|
||||||
|
{
|
||||||
|
this.Title = title;
|
||||||
|
this.Text = text;
|
||||||
|
this.Buttons = buttons;
|
||||||
|
this.DefaultButton = defaultButton;
|
||||||
|
this.DialogType = dialogType;
|
||||||
|
}
|
||||||
|
|
||||||
|
public DialogType DialogType { get => GetValue<DialogType>(); set => SetValue(value); }
|
||||||
|
public string DefaultButton { get => GetValue<string>(); set => SetValue(value); }
|
||||||
|
public string Text { get => GetValue<string>(); set => SetValue(value); }
|
||||||
|
public string[] Buttons { get => GetValue<string[]>(); set => SetValue(value); }
|
||||||
|
protected override void InitializeComponent()
|
||||||
|
{
|
||||||
|
this.ShowInTaskbar = false;
|
||||||
|
this.MaxWidth = 800;
|
||||||
|
this.MinWidth = 400;
|
||||||
|
this.MaxHeight = 600;
|
||||||
|
this.MinHeight = 250;
|
||||||
|
this.CanResize = false;
|
||||||
|
this.Width = "auto";
|
||||||
|
this.Height = "auto";
|
||||||
|
this.Background = null;
|
||||||
|
var frame = this.Children.Add(new WindowFrame(this, new Grid
|
||||||
|
{
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
RowDefinitions =
|
||||||
|
{
|
||||||
|
new RowDefinition{ Height = "auto" },
|
||||||
|
new RowDefinition{ },
|
||||||
|
new RowDefinition{ Height = 35 },
|
||||||
|
},
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new Picture
|
||||||
|
{
|
||||||
|
Stretch = Stretch.None,
|
||||||
|
Bindings =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
nameof(Visibility),
|
||||||
|
nameof(DialogType),
|
||||||
|
this,BindingMode.OneWay,
|
||||||
|
(DialogType t) => t == DialogType.None ? Visibility.Collapsed : Visibility.Visible
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nameof(Picture.Source),
|
||||||
|
nameof(DialogType),
|
||||||
|
this,BindingMode.OneWay,
|
||||||
|
(DialogType t) =>
|
||||||
|
{
|
||||||
|
switch (t)
|
||||||
|
{
|
||||||
|
case DialogType.Sucess: return "res://CPF.Toolkit/Images/sucess.png";
|
||||||
|
case DialogType.Error:return"res://CPF.Toolkit/Images/error.png";
|
||||||
|
case DialogType.Ask: return"res://CPF.Toolkit/Images/ask.png";
|
||||||
|
case DialogType.Warn:return "res://CPF.Toolkit/Images/warn.png";
|
||||||
|
default:return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
new TextBox
|
||||||
|
{
|
||||||
|
Attacheds = { { Grid.RowIndex,1 } },
|
||||||
|
BorderType = BorderType.BorderThickness,
|
||||||
|
BorderStroke = new Stroke(1, DashStyles.Solid),
|
||||||
|
BorderThickness = new Thickness(0,0,0,1),
|
||||||
|
//BorderFill = "Silver",
|
||||||
|
IsReadOnly = true,
|
||||||
|
Size = SizeField.Fill,
|
||||||
|
FontSize = 16,
|
||||||
|
WordWarp = true,
|
||||||
|
TextAlignment = TextAlignment.Center,
|
||||||
|
Bindings =
|
||||||
|
{
|
||||||
|
{ nameof(TextBox.Text),nameof(Text),this,BindingMode.OneWay}
|
||||||
|
}
|
||||||
|
}.Assign(out var textBox),
|
||||||
|
new StackPanel
|
||||||
|
{
|
||||||
|
Height = "100%",
|
||||||
|
Attacheds = { { Grid.RowIndex,2 } },
|
||||||
|
MarginBottom = 4,
|
||||||
|
Orientation = Orientation.Horizontal,
|
||||||
|
}
|
||||||
|
.LoopCreate(this.Buttons.Length, i => new Button
|
||||||
|
{
|
||||||
|
Content = this.Buttons[i],
|
||||||
|
MinWidth = this.Buttons.Length <= 1 ? 80 : 65,
|
||||||
|
Background = "white",
|
||||||
|
BorderFill = "236,236,236",
|
||||||
|
Height = "95%",
|
||||||
|
MarginRight = 5,
|
||||||
|
Commands = { { nameof(Button.Click),(s,e) => this.DialogResult = this.Buttons[i] } }
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
}));
|
||||||
|
frame.ControlBoxStroke = "black";
|
||||||
|
frame.CaptionBackgrund = "white";
|
||||||
|
frame.CaptionForeground = "black";
|
||||||
|
frame.MinimizeBox = false;
|
||||||
|
frame.MaximizeBox = false;
|
||||||
|
|
||||||
|
textBox.TextChanged += TextBox_TextChanged;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TextBox_TextChanged(object sender, EventArgs e)
|
||||||
|
{
|
||||||
|
var textBox = sender as TextBox;
|
||||||
|
if (textBox.Document.Lines.Count > 5)
|
||||||
|
{
|
||||||
|
textBox.TextAlignment = TextAlignment.Left;
|
||||||
|
textBox.Height = "100%";
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
textBox.TextAlignment = TextAlignment.Center;
|
||||||
|
textBox.Height = "auto";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected override void OnKeyUp(KeyEventArgs e)
|
||||||
|
{
|
||||||
|
if (e.Key.Or(Keys.Enter, Keys.Space))
|
||||||
|
{
|
||||||
|
var buttons = this.Find<Button>();
|
||||||
|
var btn = buttons.FirstOrDefault(x => x.IsFocused) ?? buttons.FirstOrDefault(x => x.Content?.ToString() == this.DefaultButton);
|
||||||
|
this.DialogResult = btn.Content.ToString();
|
||||||
|
e.Handled = true;
|
||||||
|
}
|
||||||
|
base.OnKeyUp(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
14
CPF.Toolkit/Dialogs/IClosable.cs
Normal file
14
CPF.Toolkit/Dialogs/IClosable.cs
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
using CPF.Controls;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit.Dialogs
|
||||||
|
{
|
||||||
|
internal interface IClosable
|
||||||
|
{
|
||||||
|
event EventHandler<ClosingEventArgs> Closable;
|
||||||
|
void OnClosable(object sender, ClosingEventArgs e);
|
||||||
|
}
|
||||||
|
}
|
73
CPF.Toolkit/Dialogs/IDialogService.cs
Normal file
73
CPF.Toolkit/Dialogs/IDialogService.cs
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
using CPF.Controls;
|
||||||
|
using CPF.Platform;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit.Dialogs
|
||||||
|
{
|
||||||
|
public interface IDialog
|
||||||
|
{
|
||||||
|
IDialogService Dialog { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
|
public interface IDialogService
|
||||||
|
{
|
||||||
|
string Alert(string text, string title, DialogType dialogType, string defaultButton, params string[] buttons);
|
||||||
|
void Alert(string text);
|
||||||
|
void Sucess(string text);
|
||||||
|
void Error(string text);
|
||||||
|
void Warn(string text);
|
||||||
|
string Ask(string text);
|
||||||
|
}
|
||||||
|
|
||||||
|
public class DialogService : IDialogService
|
||||||
|
{
|
||||||
|
public DialogService(Window owner)
|
||||||
|
{
|
||||||
|
this.owner = owner;
|
||||||
|
}
|
||||||
|
Window owner;
|
||||||
|
|
||||||
|
public string Alert(string text, string title, DialogType dialogType, string defaultButton, params string[] buttons)
|
||||||
|
{
|
||||||
|
var view = new DialogView(text, title, dialogType, defaultButton, buttons);
|
||||||
|
var result = view.ShowDialogSync(owner);
|
||||||
|
return result?.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Alert(string text)
|
||||||
|
{
|
||||||
|
this.Alert(text, "消息", DialogType.None, "确定", "确定");
|
||||||
|
}
|
||||||
|
|
||||||
|
public string Ask(string text)
|
||||||
|
{
|
||||||
|
return this.Alert(text, "询问", DialogType.Ask, "确定", "确定", "取消");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Error(string text)
|
||||||
|
{
|
||||||
|
this.Alert(text, "错误", DialogType.Error, defaultButton: "确定", "确定");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Sucess(string text)
|
||||||
|
{
|
||||||
|
this.Alert(text, "成功", DialogType.Sucess, "确定", "确定");
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Warn(string text)
|
||||||
|
{
|
||||||
|
this.Alert(text, "警告", DialogType.Warn, "确定", "确定");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum DialogType
|
||||||
|
{
|
||||||
|
None,
|
||||||
|
Sucess,
|
||||||
|
Error,
|
||||||
|
Ask,
|
||||||
|
Warn
|
||||||
|
}
|
||||||
|
}
|
13
CPF.Toolkit/Dialogs/ILoading.cs
Normal file
13
CPF.Toolkit/Dialogs/ILoading.cs
Normal file
@ -0,0 +1,13 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit.Dialogs
|
||||||
|
{
|
||||||
|
public interface ILoading
|
||||||
|
{
|
||||||
|
event Func<string, Task, Task<object>> ShowLoadingFunc;
|
||||||
|
event Func<string, Task,Task> ShowLoading;
|
||||||
|
}
|
||||||
|
}
|
BIN
CPF.Toolkit/Images/ask.png
Normal file
BIN
CPF.Toolkit/Images/ask.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 679 B |
BIN
CPF.Toolkit/Images/error.png
Normal file
BIN
CPF.Toolkit/Images/error.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 879 B |
BIN
CPF.Toolkit/Images/sucess.png
Normal file
BIN
CPF.Toolkit/Images/sucess.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 834 B |
BIN
CPF.Toolkit/Images/warn.png
Normal file
BIN
CPF.Toolkit/Images/warn.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 748 B |
63
CPF.Toolkit/ObservableObject.cs
Normal file
63
CPF.Toolkit/ObservableObject.cs
Normal file
@ -0,0 +1,63 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Concurrent;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.ComponentModel;
|
||||||
|
using System.Runtime.CompilerServices;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit
|
||||||
|
{
|
||||||
|
public class ObservableObject : INotifyPropertyChanged
|
||||||
|
{
|
||||||
|
readonly ConcurrentDictionary<string, object> Propertys = new ConcurrentDictionary<string, object> { };
|
||||||
|
public event PropertyChangedEventHandler PropertyChanged;
|
||||||
|
|
||||||
|
|
||||||
|
public T GetValue<T>(T defaultValue = default, [CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(propertyName))
|
||||||
|
{
|
||||||
|
throw new Exception("propertyName不能为空");
|
||||||
|
}
|
||||||
|
if (!this.Propertys.ContainsKey(propertyName))
|
||||||
|
{
|
||||||
|
this.Propertys.TryAdd(propertyName, defaultValue);
|
||||||
|
}
|
||||||
|
return (T)this.Propertys[propertyName];
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool SetValue<T>(T value, [CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
if (string.IsNullOrEmpty(propertyName))
|
||||||
|
{
|
||||||
|
throw new Exception("propertyName不能为空");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!this.Propertys.ContainsKey(propertyName))
|
||||||
|
{
|
||||||
|
this.Propertys.TryAdd(propertyName, value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var v = this.GetValue<T>(propertyName: propertyName);
|
||||||
|
if (EqualityComparer<T>.Default.Equals(value, v)) return false;
|
||||||
|
this.Propertys[propertyName] = value;
|
||||||
|
}
|
||||||
|
this.RaisePropertyChanged(propertyName);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetValue<T>(T value, Action<T> action, [CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
if (this.SetValue(value, propertyName))
|
||||||
|
{
|
||||||
|
action.Invoke(value);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void RaisePropertyChanged([CallerMemberName] string propertyName = null)
|
||||||
|
{
|
||||||
|
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
46
CPF.Toolkit/ToolkitHelper.cs
Normal file
46
CPF.Toolkit/ToolkitHelper.cs
Normal file
@ -0,0 +1,46 @@
|
|||||||
|
using CPF.Controls;
|
||||||
|
using CPF.Toolkit.Dialogs;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit
|
||||||
|
{
|
||||||
|
public static class ToolkitHelper
|
||||||
|
{
|
||||||
|
|
||||||
|
internal static void CreateLoading(this ILoading loading,UIElement uIElement)
|
||||||
|
{
|
||||||
|
loading.ShowLoadingFunc += async (message, task) =>
|
||||||
|
{
|
||||||
|
var loadingBox = new LoadingBox { Message = message };
|
||||||
|
var layer = new LayerDialog
|
||||||
|
{
|
||||||
|
Name = "loadingDialog",
|
||||||
|
Content = loadingBox,
|
||||||
|
ShowCloseButton = false,
|
||||||
|
Background = null,
|
||||||
|
};
|
||||||
|
layer.ShowDialog(uIElement);
|
||||||
|
dynamic t = task;
|
||||||
|
var result = await t;
|
||||||
|
loadingBox.Invoke(layer.CloseDialog);
|
||||||
|
return result;
|
||||||
|
};
|
||||||
|
loading.ShowLoading += async (message, task) =>
|
||||||
|
{
|
||||||
|
var loadingBox = new LoadingBox { Message = message };
|
||||||
|
var layer = new LayerDialog
|
||||||
|
{
|
||||||
|
Name = "loadingDialog",
|
||||||
|
Content = loadingBox,
|
||||||
|
ShowCloseButton = false,
|
||||||
|
Background = null,
|
||||||
|
};
|
||||||
|
layer.ShowDialog(uIElement);
|
||||||
|
await task;
|
||||||
|
loadingBox.Invoke(layer.CloseDialog);
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
52
CPF.Toolkit/ViewManager.cs
Normal file
52
CPF.Toolkit/ViewManager.cs
Normal file
@ -0,0 +1,52 @@
|
|||||||
|
using CPF.Controls;
|
||||||
|
using CPF.Toolkit.Dialogs;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit
|
||||||
|
{
|
||||||
|
public static class ViewManager
|
||||||
|
{
|
||||||
|
public static T View<T>(params object[] arges) where T : Window
|
||||||
|
{
|
||||||
|
var view = Activator.CreateInstance(typeof(T), arges) as T;
|
||||||
|
view.Closing += View_Closing;
|
||||||
|
view.PropertyChanged += View_PropertyChanged;
|
||||||
|
return view;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void View_PropertyChanged(object sender, CPFPropertyChangedEventArgs e)
|
||||||
|
{
|
||||||
|
var view = sender as Window;
|
||||||
|
if (e.PropertyName == nameof(Window.DataContext))
|
||||||
|
{
|
||||||
|
if (view.DataContext is IClosable closable)
|
||||||
|
{
|
||||||
|
closable.Closable += (ss, ee) =>
|
||||||
|
{
|
||||||
|
view.Close();
|
||||||
|
};
|
||||||
|
}
|
||||||
|
if (view.DataContext is IDialog dialog)
|
||||||
|
{
|
||||||
|
dialog.Dialog = new DialogService(view);
|
||||||
|
}
|
||||||
|
if (view.DataContext is ILoading loading)
|
||||||
|
{
|
||||||
|
loading.CreateLoading(view);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void View_Closing(object sender, ClosingEventArgs e)
|
||||||
|
{
|
||||||
|
var view = sender as Window;
|
||||||
|
if (view.DataContext is IClosable closable)
|
||||||
|
{
|
||||||
|
closable.OnClosable(sender, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
50
CPF.Toolkit/ViewModelBase.cs
Normal file
50
CPF.Toolkit/ViewModelBase.cs
Normal file
@ -0,0 +1,50 @@
|
|||||||
|
using CPF.Controls;
|
||||||
|
using CPF.Toolkit.Dialogs;
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CPF.Toolkit
|
||||||
|
{
|
||||||
|
public class ViewModelBase : ObservableObject, IClosable, IDialog, ILoading
|
||||||
|
{
|
||||||
|
event EventHandler<ClosingEventArgs> _close;
|
||||||
|
event Func<string, Task, Task<object>> _showLoadingFunc;
|
||||||
|
event Func<string, Task, Task> _showLading;
|
||||||
|
event EventHandler<ClosingEventArgs> IClosable.Closable { add => this._close += value; remove => this._close -= value; }
|
||||||
|
event Func<string, Task, Task<object>> ILoading.ShowLoadingFunc { add => this._showLoadingFunc += value; remove => this._showLoadingFunc -= value; }
|
||||||
|
event Func<string, Task, Task> ILoading.ShowLoading { add => this._showLading += value; remove => this._showLading -= value; }
|
||||||
|
|
||||||
|
void IClosable.OnClosable(object sender, ClosingEventArgs e) => this.OnClose(e);
|
||||||
|
|
||||||
|
public IDialogService Dialog { get; set; }
|
||||||
|
|
||||||
|
protected void Close()
|
||||||
|
{
|
||||||
|
if (this._close == null) throw new ArgumentNullException();
|
||||||
|
this._close.Invoke(this, new ClosingEventArgs());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual void OnClose(ClosingEventArgs e) { }
|
||||||
|
|
||||||
|
protected async Task ShowLoading(Task task)
|
||||||
|
{
|
||||||
|
if (this._showLading == null) throw new ArgumentNullException();
|
||||||
|
await this._showLading.Invoke("加载中……", task);
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task ShowLoading(Func<Task> task)
|
||||||
|
{
|
||||||
|
if (this._showLoadingFunc == null) throw new ArgumentNullException();
|
||||||
|
await this._showLading.Invoke("加载中……", task.Invoke());
|
||||||
|
}
|
||||||
|
|
||||||
|
protected async Task<T> ShowLoading<T>(Func<Task<T>> task)
|
||||||
|
{
|
||||||
|
if (this._showLoadingFunc == null) throw new ArgumentNullException();
|
||||||
|
var result = await this._showLoadingFunc.Invoke("加载中……", task.Invoke());
|
||||||
|
return (T)result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -3,6 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CPF
|
namespace CPF
|
||||||
{
|
{
|
||||||
@ -163,6 +164,7 @@ namespace CPF
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 右边数据绑定到左边,只传递一次数据
|
/// 右边数据绑定到左边,只传递一次数据
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -451,6 +453,7 @@ namespace CPF
|
|||||||
public class CommandDescribe
|
public class CommandDescribe
|
||||||
{
|
{
|
||||||
public Action<CpfObject, object> Action { get; set; }
|
public Action<CpfObject, object> Action { get; set; }
|
||||||
|
public Func<CpfObject, object, Task> AsyncAction { get; set; }
|
||||||
|
|
||||||
public string MethodName { get; set; }
|
public string MethodName { get; set; }
|
||||||
public object[] Parameters { get; set; }
|
public object[] Parameters { get; set; }
|
||||||
@ -466,6 +469,11 @@ namespace CPF
|
|||||||
{
|
{
|
||||||
Action = command;
|
Action = command;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public CommandDescribe(Func<CpfObject, object, Task> command)
|
||||||
|
{
|
||||||
|
this.AsyncAction = command;
|
||||||
|
}
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 定义个命令绑定
|
/// 定义个命令绑定
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CPF
|
namespace CPF
|
||||||
{
|
{
|
||||||
@ -108,6 +109,17 @@ namespace CPF
|
|||||||
list.Add(new Command { Action = action });
|
list.Add(new Command { Action = action });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void Add(string eventName, Func<CpfObject, object, Task> action)
|
||||||
|
{
|
||||||
|
List<Command> list;
|
||||||
|
if (!commands.TryGetValue(eventName, out list))
|
||||||
|
{
|
||||||
|
list = new List<Command>();
|
||||||
|
commands.Add(eventName, list);
|
||||||
|
}
|
||||||
|
list.Add(new Command { AsyncAction = action });
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// KeyValuePair<string, List<Command>>
|
/// KeyValuePair<string, List<Command>>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -133,6 +145,6 @@ namespace CPF
|
|||||||
public object[] Params;
|
public object[] Params;
|
||||||
//public Relation Relation;
|
//public Relation Relation;
|
||||||
public Action<CpfObject, object> Action;
|
public Action<CpfObject, object> Action;
|
||||||
|
public Func<CpfObject, object, Task> AsyncAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -16,8 +16,56 @@ namespace CPF.Controls
|
|||||||
{
|
{
|
||||||
protected override void InitializeComponent()
|
protected override void InitializeComponent()
|
||||||
{
|
{
|
||||||
this.Triggers.Add(nameof(IsMouseOver), Relation.Me, null, (nameof(Background), "190,230,253"));
|
//this.MinWidth = 80;
|
||||||
this.Triggers.Add(nameof(IsPressed), Relation.Me, null, (nameof(Background), "186,209,226"));
|
//this.MinHeight = 35;
|
||||||
|
//this.MarginRight = 1;
|
||||||
|
this.Triggers.Add(new Trigger
|
||||||
|
{
|
||||||
|
Property = nameof(IsMouseOver),
|
||||||
|
TargetRelation = Relation.Me,
|
||||||
|
PropertyConditions = x => Convert.ToBoolean(x),
|
||||||
|
Setters =
|
||||||
|
{
|
||||||
|
{ nameof(Background),"#E5F1FB" },
|
||||||
|
{ nameof(BorderFill),"#0078D7" },
|
||||||
|
{ nameof(Foreground),"black" },
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.Triggers.Add(new Trigger
|
||||||
|
{
|
||||||
|
Property = nameof(IsPressed),
|
||||||
|
TargetRelation = Relation.Me,
|
||||||
|
PropertyConditions = x => Convert.ToBoolean(x),
|
||||||
|
Setters =
|
||||||
|
{
|
||||||
|
{ nameof(Background),"204,228,247" },
|
||||||
|
{ nameof(BorderFill),"0,84,153" },
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.Triggers.Add(new Trigger
|
||||||
|
{
|
||||||
|
Property = nameof(IsFocused),
|
||||||
|
TargetRelation = Relation.Me,
|
||||||
|
PropertyConditions = x => Convert.ToBoolean(x),
|
||||||
|
Setters =
|
||||||
|
{
|
||||||
|
{ nameof(Background),"204,228,247" },
|
||||||
|
{ nameof(BorderFill),"0,120,215" },
|
||||||
|
{ nameof(BorderStroke),"2" },
|
||||||
|
}
|
||||||
|
});
|
||||||
|
this.triggers.Add(new Trigger
|
||||||
|
{
|
||||||
|
Property = nameof(IsEnabled),
|
||||||
|
TargetRelation = Relation.Me,
|
||||||
|
PropertyConditions = x => !Convert.ToBoolean(x),
|
||||||
|
Setters =
|
||||||
|
{
|
||||||
|
{ nameof(Background),"204,204,204" },
|
||||||
|
{ nameof(BorderFill),"191,191,191" },
|
||||||
|
{ nameof(Foreground),"131,131,131" },
|
||||||
|
}
|
||||||
|
});
|
||||||
Children.Add(new Border
|
Children.Add(new Border
|
||||||
{
|
{
|
||||||
Name = "contentPresenter",
|
Name = "contentPresenter",
|
||||||
@ -33,11 +81,13 @@ namespace CPF.Controls
|
|||||||
{
|
{
|
||||||
base.OnOverrideMetadata(overridePropertys);
|
base.OnOverrideMetadata(overridePropertys);
|
||||||
overridePropertys.Override(nameof(BorderStroke), new UIPropertyMetadataAttribute(typeof(Stroke), "1", UIPropertyOptions.AffectsRender));
|
overridePropertys.Override(nameof(BorderStroke), new UIPropertyMetadataAttribute(typeof(Stroke), "1", UIPropertyOptions.AffectsRender));
|
||||||
overridePropertys.Override(nameof(BorderFill), new UIPropertyMetadataAttribute((ViewFill)"#101010", UIPropertyOptions.AffectsRender));
|
overridePropertys.Override(nameof(BorderFill), new UIPropertyMetadataAttribute((ViewFill)"#ADADAD", UIPropertyOptions.AffectsRender));
|
||||||
overridePropertys.Override(nameof(IsAntiAlias), new UIPropertyMetadataAttribute(false, UIPropertyOptions.AffectsRender));
|
overridePropertys.Override(nameof(IsAntiAlias), new UIPropertyMetadataAttribute(false, UIPropertyOptions.AffectsRender));
|
||||||
overridePropertys.Override(nameof(Background), new UIPropertyMetadataAttribute((ViewFill)"221,221,221", UIPropertyOptions.AffectsRender));
|
overridePropertys.Override(nameof(Background), new UIPropertyMetadataAttribute((ViewFill)"#E1E1E1", UIPropertyOptions.AffectsRender));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue, PropertyMetadataAttribute propertyMetadata)
|
//protected override void OnPropertyChanged(string propertyName, object oldValue, object newValue, PropertyMetadataAttribute propertyMetadata)
|
||||||
//{
|
//{
|
||||||
// base.OnPropertyChanged(propertyName, oldValue, newValue, propertyMetadata);
|
// base.OnPropertyChanged(propertyName, oldValue, newValue, propertyMetadata);
|
||||||
|
@ -4,6 +4,7 @@ using System.Text;
|
|||||||
using CPF.Input;
|
using CPF.Input;
|
||||||
using CPF.Drawing;
|
using CPF.Drawing;
|
||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CPF.Controls
|
namespace CPF.Controls
|
||||||
{
|
{
|
||||||
@ -72,6 +73,7 @@ namespace CPF.Controls
|
|||||||
try
|
try
|
||||||
{
|
{
|
||||||
OnClick();
|
OnClick();
|
||||||
|
OnAsyncClick();
|
||||||
exceptionThrown = false;
|
exceptionThrown = false;
|
||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
@ -128,6 +130,7 @@ namespace CPF.Controls
|
|||||||
if (l.X >= 0 && l.Y >= 0 && l.X <= r.Width && l.Y <= r.Height)
|
if (l.X >= 0 && l.Y >= 0 && l.X <= r.Width && l.Y <= r.Height)
|
||||||
{
|
{
|
||||||
OnClick();
|
OnClick();
|
||||||
|
OnAsyncClick();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -159,6 +162,7 @@ namespace CPF.Controls
|
|||||||
if (ClickMode == ClickMode.Press)
|
if (ClickMode == ClickMode.Press)
|
||||||
{
|
{
|
||||||
OnClick();
|
OnClick();
|
||||||
|
OnAsyncClick();
|
||||||
}
|
}
|
||||||
|
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
@ -177,6 +181,7 @@ namespace CPF.Controls
|
|||||||
}
|
}
|
||||||
|
|
||||||
OnClick();
|
OnClick();
|
||||||
|
OnAsyncClick();
|
||||||
e.Handled = true;
|
e.Handled = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -222,7 +227,10 @@ namespace CPF.Controls
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (shouldClick)
|
if (shouldClick)
|
||||||
|
{
|
||||||
OnClick();
|
OnClick();
|
||||||
|
OnAsyncClick();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -250,15 +258,10 @@ namespace CPF.Controls
|
|||||||
IsPressed = false;
|
IsPressed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void OnClick()
|
protected void OnClick()
|
||||||
{
|
{
|
||||||
//var p1 = PointToScreen(new Point());
|
|
||||||
//var p4 = PointToScreen(new Point(ActualSize.Width, ActualSize.Height));
|
|
||||||
//var rect = new Rect(p1, p4);
|
|
||||||
//if (rect.Contains(Root.InputManager.MouseDevice.Location))
|
|
||||||
//{
|
|
||||||
OnClick(new RoutedEventArgs(this));
|
OnClick(new RoutedEventArgs(this));
|
||||||
//}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected virtual void OnClick(RoutedEventArgs e)
|
protected virtual void OnClick(RoutedEventArgs e)
|
||||||
@ -266,6 +269,18 @@ namespace CPF.Controls
|
|||||||
RaiseEvent(e, nameof(Click));
|
RaiseEvent(e, nameof(Click));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected async Task OnAsyncClick()
|
||||||
|
{
|
||||||
|
await OnAsyncClick(new RoutedEventArgs(this));
|
||||||
|
}
|
||||||
|
|
||||||
|
protected virtual async Task OnAsyncClick(RoutedEventArgs e)
|
||||||
|
{
|
||||||
|
this.IsEnabled = false;
|
||||||
|
await AsyncRaiseEvent(e, nameof(AsyncClick));
|
||||||
|
this.IsEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 获取或设置 Click 事件何时发生。
|
/// 获取或设置 Click 事件何时发生。
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -296,6 +311,12 @@ namespace CPF.Controls
|
|||||||
add { AddHandler(value); }
|
add { AddHandler(value); }
|
||||||
remove { RemoveHandler(value); }
|
remove { RemoveHandler(value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public event AsyncEventHandler<RoutedEventArgs> AsyncClick
|
||||||
|
{
|
||||||
|
add { AddHandler(value); }
|
||||||
|
remove { RemoveHandler(value); }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
@ -27,7 +27,7 @@ namespace CPF.Controls
|
|||||||
public static IEnumerable<Window> Windows { get { return windows; } }
|
public static IEnumerable<Window> Windows { get { return windows; } }
|
||||||
|
|
||||||
IWindowImpl windowImpl;
|
IWindowImpl windowImpl;
|
||||||
|
bool? isDialog;
|
||||||
public event EventHandler Closed
|
public event EventHandler Closed
|
||||||
{
|
{
|
||||||
add { AddHandler(value); }
|
add { AddHandler(value); }
|
||||||
@ -314,8 +314,11 @@ namespace CPF.Controls
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool? IsDialogMode => this.isDialog;
|
||||||
|
|
||||||
void SetDialog(bool enable, Window child)
|
void SetDialog(bool enable, Window child)
|
||||||
{
|
{
|
||||||
|
this.isDialog = true;
|
||||||
if (dialogChildren == null)
|
if (dialogChildren == null)
|
||||||
{
|
{
|
||||||
dialogChildren = new HashSet<Window>();
|
dialogChildren = new HashSet<Window>();
|
||||||
|
@ -10,6 +10,7 @@ using CPF.Effects;
|
|||||||
using System.ComponentModel;
|
using System.ComponentModel;
|
||||||
using CPF.Controls;
|
using CPF.Controls;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace CPF.Controls
|
namespace CPF.Controls
|
||||||
{
|
{
|
||||||
@ -94,10 +95,22 @@ namespace CPF.Controls
|
|||||||
set { SetValue(value); }
|
set { SetValue(value); }
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[PropertyMetadata(typeof(ViewFill), "white")]
|
||||||
|
public ViewFill ControlBoxStroke { get => GetValue<ViewFill>(); set => SetValue(value); }
|
||||||
|
|
||||||
|
[PropertyMetadata(typeof(ViewFill), "#1E9FFF")]
|
||||||
|
public ViewFill CaptionBackgrund { get => GetValue<ViewFill>(); set => SetValue(value); }
|
||||||
|
|
||||||
|
[PropertyMetadata(typeof(ViewFill), "white")]
|
||||||
|
public ViewFill CaptionForeground { get => GetValue<ViewFill>(); set => SetValue(value); }
|
||||||
|
|
||||||
|
[PropertyMetadata(typeof(FloatField), "35")]
|
||||||
|
public FloatField CaptionHeight { get => GetValue<FloatField>(); set => SetValue(value); }
|
||||||
|
|
||||||
|
|
||||||
protected override void InitializeComponent()
|
protected override void InitializeComponent()
|
||||||
{
|
{
|
||||||
|
//ViewFill color = "#fff";
|
||||||
ViewFill color = "#fff";
|
|
||||||
ViewFill hoverColor = "255,255,255,40";
|
ViewFill hoverColor = "255,255,255,40";
|
||||||
Width = "100%";
|
Width = "100%";
|
||||||
Height = "100%";
|
Height = "100%";
|
||||||
@ -160,341 +173,354 @@ namespace CPF.Controls
|
|||||||
});
|
});
|
||||||
//标题栏和按钮
|
//标题栏和按钮
|
||||||
grid.Children.Add(
|
grid.Children.Add(
|
||||||
new Panel
|
new Panel
|
||||||
{
|
|
||||||
Name = "caption",
|
|
||||||
Background = "#1E9FFF",
|
|
||||||
Width = "100%",
|
|
||||||
Height = "30",
|
|
||||||
Commands =
|
|
||||||
{
|
{
|
||||||
|
Name = "caption",
|
||||||
|
Width = "100%",
|
||||||
|
Bindings =
|
||||||
{
|
{
|
||||||
nameof(MouseDown),
|
{ nameof(Panel.Background),nameof(this.CaptionBackgrund),this},
|
||||||
nameof(IWindow.DragMove),
|
{ nameof(Panel.Height),nameof(this.CaptionHeight),this},
|
||||||
Window
|
|
||||||
},
|
},
|
||||||
|
Commands =
|
||||||
{
|
{
|
||||||
nameof(DoubleClick),
|
|
||||||
(s,e)=> DoubleClickTitle()
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Children =
|
|
||||||
{
|
|
||||||
new StackPanel
|
|
||||||
{
|
|
||||||
Name="titleBox",
|
|
||||||
MarginLeft=0,
|
|
||||||
Orientation= Orientation.Horizontal,
|
|
||||||
Children=
|
|
||||||
{
|
{
|
||||||
new Picture
|
nameof(MouseDown),
|
||||||
{
|
nameof(IWindow.DragMove),
|
||||||
Name="icon",
|
Window
|
||||||
MarginLeft=5,
|
},
|
||||||
Width=20,
|
{
|
||||||
Height=20,
|
nameof(DoubleClick),
|
||||||
Stretch= Stretch.Fill,
|
(s,e)=> DoubleClickTitle()
|
||||||
Bindings=
|
|
||||||
{
|
|
||||||
{
|
|
||||||
nameof(Picture.Source),
|
|
||||||
nameof(window.Icon),
|
|
||||||
window
|
|
||||||
},
|
|
||||||
{
|
|
||||||
nameof(Visibility),
|
|
||||||
nameof(window.Icon),
|
|
||||||
window,
|
|
||||||
BindingMode.OneWay,
|
|
||||||
a=>a==null||!ShowIcon?Visibility.Collapsed:Visibility.Visible
|
|
||||||
},
|
|
||||||
{
|
|
||||||
nameof(Visibility),
|
|
||||||
nameof(ShowIcon),
|
|
||||||
this,
|
|
||||||
BindingMode.OneWay,
|
|
||||||
(bool showIcon)=>!showIcon||window.Icon==null?Visibility.Collapsed:Visibility.Visible
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new TextBlock
|
|
||||||
{
|
|
||||||
Name="title",
|
|
||||||
MarginLeft=8,
|
|
||||||
MarginTop=2,
|
|
||||||
Bindings=
|
|
||||||
{
|
|
||||||
{
|
|
||||||
nameof(TextBlock.Text),
|
|
||||||
nameof(IWindow.Title),
|
|
||||||
Window
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Foreground="#fff"
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
new StackPanel
|
Children =
|
||||||
{
|
{
|
||||||
Name="controlBox",
|
new StackPanel
|
||||||
MarginRight=0,
|
|
||||||
Height = "100%",
|
|
||||||
Orientation= Orientation.Horizontal,
|
|
||||||
Children =
|
|
||||||
{
|
{
|
||||||
systemButtons,
|
Name="titleBox",
|
||||||
new SystemButton
|
MarginLeft=0,
|
||||||
|
Orientation= Orientation.Horizontal,
|
||||||
|
Children=
|
||||||
{
|
{
|
||||||
ToolTip="最小化",
|
new Picture
|
||||||
Name="min",
|
|
||||||
Width = 30,
|
|
||||||
Height = "100%",
|
|
||||||
Content=
|
|
||||||
new Line
|
|
||||||
{
|
|
||||||
MarginLeft="auto",
|
|
||||||
MarginTop=5,
|
|
||||||
StartPoint = new Point(1, 13),
|
|
||||||
EndPoint = new Point(14, 13),
|
|
||||||
StrokeStyle = "2",
|
|
||||||
IsAntiAlias=true,
|
|
||||||
StrokeFill=color
|
|
||||||
},
|
|
||||||
Bindings=
|
|
||||||
{
|
{
|
||||||
|
Name="icon",
|
||||||
|
MarginLeft=5,
|
||||||
|
Width=20,
|
||||||
|
Height=20,
|
||||||
|
Stretch= Stretch.Fill,
|
||||||
|
Bindings=
|
||||||
{
|
{
|
||||||
nameof(Visibility),
|
|
||||||
nameof(MinimizeBox),
|
|
||||||
this,
|
|
||||||
BindingMode.OneWay,
|
|
||||||
a=>(bool)a?Visibility.Visible: Visibility.Collapsed
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Commands =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
nameof(Button.Click),
|
|
||||||
(s,e)=>
|
|
||||||
{
|
{
|
||||||
//(e as MouseButtonEventArgs).Handled = true;
|
nameof(Picture.Source),
|
||||||
Window.WindowState = WindowState.Minimized;
|
nameof(window.Icon),
|
||||||
|
window
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nameof(Visibility),
|
||||||
|
nameof(window.Icon),
|
||||||
|
window,
|
||||||
|
BindingMode.OneWay,
|
||||||
|
a=>a==null||!ShowIcon?Visibility.Collapsed:Visibility.Visible
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nameof(Visibility),
|
||||||
|
nameof(ShowIcon),
|
||||||
|
this,
|
||||||
|
BindingMode.OneWay,
|
||||||
|
(bool showIcon)=>!showIcon||window.Icon==null?Visibility.Collapsed:Visibility.Visible
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
Triggers=
|
new TextBlock
|
||||||
{
|
{
|
||||||
new Trigger(nameof(Panel.IsMouseOver), Relation.Me)
|
Name="title",
|
||||||
|
MarginLeft=8,
|
||||||
|
MarginTop=2,
|
||||||
|
Bindings=
|
||||||
{
|
{
|
||||||
Setters =
|
|
||||||
{
|
{
|
||||||
{
|
nameof(TextBlock.Text),
|
||||||
nameof(Panel.Background),
|
nameof(IWindow.Title),
|
||||||
hoverColor
|
Window
|
||||||
}
|
},
|
||||||
}
|
{ nameof(TextBlock.Foreground),nameof(this.CaptionForeground),this }
|
||||||
}
|
},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
,
|
},
|
||||||
new Panel
|
new StackPanel
|
||||||
|
{
|
||||||
|
Name="controlBox",
|
||||||
|
MarginRight=0,
|
||||||
|
Height = "100%",
|
||||||
|
Orientation= Orientation.Horizontal,
|
||||||
|
Children =
|
||||||
{
|
{
|
||||||
Height = "100%",
|
systemButtons,
|
||||||
Bindings=
|
new SystemButton
|
||||||
{
|
{
|
||||||
|
ToolTip="最小化",
|
||||||
|
Name="min",
|
||||||
|
Width = 30,
|
||||||
|
Height = "100%",
|
||||||
|
Content=
|
||||||
|
new Line
|
||||||
{
|
{
|
||||||
nameof(Visibility),
|
MarginLeft="auto",
|
||||||
nameof(MaximizeBox),
|
MarginTop=5,
|
||||||
this,
|
StartPoint = new Point(1, 13),
|
||||||
BindingMode.OneWay,
|
EndPoint = new Point(14, 13),
|
||||||
a=>(bool)a?Visibility.Visible: Visibility.Collapsed
|
StrokeStyle = "2",
|
||||||
}
|
IsAntiAlias=true,
|
||||||
},
|
//StrokeFill=color
|
||||||
Children=
|
Bindings =
|
||||||
|
{
|
||||||
|
{ nameof(Line.StrokeFill),nameof(this.ControlBoxStroke),this}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Bindings=
|
||||||
|
{
|
||||||
|
{
|
||||||
|
nameof(Visibility),
|
||||||
|
nameof(MinimizeBox),
|
||||||
|
this,
|
||||||
|
BindingMode.OneWay,
|
||||||
|
a=>(bool)a?Visibility.Visible: Visibility.Collapsed
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Commands =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
nameof(Button.Click),
|
||||||
|
(s,e)=>
|
||||||
|
{
|
||||||
|
//(e as MouseButtonEventArgs).Handled = true;
|
||||||
|
Window.WindowState = WindowState.Minimized;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Triggers=
|
||||||
|
{
|
||||||
|
new Trigger(nameof(Panel.IsMouseOver), Relation.Me)
|
||||||
|
{
|
||||||
|
Setters =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
nameof(Panel.Background),
|
||||||
|
hoverColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
|
,
|
||||||
|
new Panel
|
||||||
{
|
{
|
||||||
new SystemButton
|
Height = "100%",
|
||||||
|
Bindings=
|
||||||
{
|
{
|
||||||
ToolTip="最大化",
|
{
|
||||||
Name="max",
|
nameof(Visibility),
|
||||||
Width = 30,
|
nameof(MaximizeBox),
|
||||||
Height = "100%",
|
this,
|
||||||
Content=
|
BindingMode.OneWay,
|
||||||
new Rectangle
|
a=>(bool)a?Visibility.Visible: Visibility.Collapsed
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Children=
|
||||||
|
{
|
||||||
|
new SystemButton
|
||||||
|
{
|
||||||
|
ToolTip="最大化",
|
||||||
|
Name="max",
|
||||||
|
Width = 30,
|
||||||
|
Height = "100%",
|
||||||
|
Content= new Rectangle
|
||||||
{
|
{
|
||||||
Width=14,
|
Width=14,
|
||||||
Height=12,
|
Height=12,
|
||||||
MarginTop=10,
|
MarginTop=10,
|
||||||
StrokeStyle="2",
|
StrokeStyle="2",
|
||||||
StrokeFill = color
|
Bindings =
|
||||||
|
{
|
||||||
|
{ nameof(Line.StrokeFill),nameof(this.ControlBoxStroke),this}
|
||||||
|
}
|
||||||
},
|
},
|
||||||
Commands =
|
Commands =
|
||||||
{
|
|
||||||
{
|
{
|
||||||
nameof(Button.Click),
|
|
||||||
(s,e)=>
|
|
||||||
{
|
|
||||||
//(e as MouseButtonEventArgs).Handled = true;
|
|
||||||
Window.WindowState= WindowState.Maximized;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Bindings =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
nameof(Border.Visibility),
|
|
||||||
nameof(Window.WindowState),
|
|
||||||
Window,
|
|
||||||
BindingMode.OneWay,
|
|
||||||
a => (WindowState)a == WindowState.Maximized||(WindowState)a == WindowState.FullScreen ? Visibility.Collapsed : Visibility.Visible
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Triggers=
|
|
||||||
{
|
|
||||||
new Trigger(nameof(Panel.IsMouseOver), Relation.Me)
|
|
||||||
{
|
|
||||||
Setters =
|
|
||||||
{
|
{
|
||||||
|
nameof(Button.Click),
|
||||||
|
(s,e)=>
|
||||||
{
|
{
|
||||||
nameof(Panel.Background),
|
//(e as MouseButtonEventArgs).Handled = true;
|
||||||
hoverColor
|
Window.WindowState= WindowState.Maximized;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
Bindings =
|
||||||
},
|
|
||||||
new SystemButton
|
|
||||||
{
|
|
||||||
ToolTip="向下还原",
|
|
||||||
Name="nor",
|
|
||||||
Width = 30,
|
|
||||||
Height = "100%",
|
|
||||||
Content=new Panel{
|
|
||||||
Size=SizeField.Fill,
|
|
||||||
Children=
|
|
||||||
{
|
{
|
||||||
new Rectangle
|
|
||||||
{
|
{
|
||||||
MarginTop=15,
|
nameof(Border.Visibility),
|
||||||
MarginLeft=8,
|
nameof(Window.WindowState),
|
||||||
Width=11,
|
Window,
|
||||||
Height=8,
|
BindingMode.OneWay,
|
||||||
StrokeStyle="1.5",
|
a => (WindowState)a == WindowState.Maximized||(WindowState)a == WindowState.FullScreen ? Visibility.Collapsed : Visibility.Visible
|
||||||
StrokeFill = color
|
}
|
||||||
},
|
},
|
||||||
new Polyline
|
Triggers=
|
||||||
|
{
|
||||||
|
new Trigger(nameof(Panel.IsMouseOver), Relation.Me)
|
||||||
{
|
{
|
||||||
MarginTop=11,
|
Setters =
|
||||||
MarginLeft=12,
|
|
||||||
Points=
|
|
||||||
{
|
{
|
||||||
new Point(0,3),
|
{
|
||||||
new Point(0,0),
|
nameof(Panel.Background),
|
||||||
new Point(9,0),
|
hoverColor
|
||||||
new Point(9,7),
|
}
|
||||||
new Point(6,7)
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
},
|
||||||
|
new SystemButton
|
||||||
|
{
|
||||||
|
ToolTip="向下还原",
|
||||||
|
Name="nor",
|
||||||
|
Width = 30,
|
||||||
|
Height = "100%",
|
||||||
|
Content=new Panel{
|
||||||
|
Size=SizeField.Fill,
|
||||||
|
Children=
|
||||||
|
{
|
||||||
|
new Rectangle
|
||||||
|
{
|
||||||
|
MarginTop=15,
|
||||||
|
MarginLeft=8,
|
||||||
|
Width=11,
|
||||||
|
Height=8,
|
||||||
|
StrokeStyle="1.5",
|
||||||
|
//StrokeFill = color
|
||||||
|
Bindings = { { nameof(Line.StrokeFill), nameof(this.ControlBoxStroke), this } },
|
||||||
},
|
},
|
||||||
StrokeFill = color,
|
new Polyline
|
||||||
StrokeStyle="2"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Commands =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
nameof(Button.Click),
|
|
||||||
(s,e)=>
|
|
||||||
{
|
|
||||||
//(e as MouseButtonEventArgs).Handled = true;
|
|
||||||
Window.WindowState = WindowState.Normal;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Bindings =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
nameof(Border.Visibility),
|
|
||||||
nameof(Window.WindowState),
|
|
||||||
Window,
|
|
||||||
BindingMode.OneWay,
|
|
||||||
a => (WindowState)a == WindowState.Normal ? Visibility.Collapsed : Visibility.Visible
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Triggers=
|
|
||||||
{
|
|
||||||
new Trigger(nameof(Panel.IsMouseOver), Relation.Me)
|
|
||||||
{
|
|
||||||
Setters =
|
|
||||||
{
|
|
||||||
{
|
{
|
||||||
nameof(Panel.Background),
|
MarginTop=11,
|
||||||
hoverColor
|
MarginLeft=12,
|
||||||
|
Points=
|
||||||
|
{
|
||||||
|
new Point(0,3),
|
||||||
|
new Point(0,0),
|
||||||
|
new Point(9,0),
|
||||||
|
new Point(9,7),
|
||||||
|
new Point(6,7)
|
||||||
|
},
|
||||||
|
//StrokeFill = color,
|
||||||
|
Bindings = { { nameof(Line.StrokeFill), nameof(this.ControlBoxStroke), this } },
|
||||||
|
StrokeStyle="2"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
},
|
Commands =
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
new SystemButton
|
|
||||||
{
|
|
||||||
Name="close",
|
|
||||||
ToolTip="关闭",
|
|
||||||
Width = 30,
|
|
||||||
Height = "100%",
|
|
||||||
Content=new Panel{
|
|
||||||
Size=SizeField.Fill,
|
|
||||||
Children =
|
|
||||||
{
|
|
||||||
new Line
|
|
||||||
{
|
|
||||||
MarginTop=8,
|
|
||||||
MarginLeft=8,
|
|
||||||
StartPoint = new Point(1, 1),
|
|
||||||
EndPoint = new Point(14, 13),
|
|
||||||
StrokeStyle = "2",
|
|
||||||
IsAntiAlias=true,
|
|
||||||
StrokeFill=color
|
|
||||||
},
|
|
||||||
new Line
|
|
||||||
{
|
|
||||||
MarginTop=8,
|
|
||||||
MarginLeft=8,
|
|
||||||
StartPoint = new Point(14, 1),
|
|
||||||
EndPoint = new Point(1, 13),
|
|
||||||
StrokeStyle = "2",
|
|
||||||
IsAntiAlias=true,
|
|
||||||
StrokeFill=color
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Commands =
|
|
||||||
{
|
|
||||||
{
|
|
||||||
nameof(Button.Click),
|
|
||||||
(s,e)=>
|
|
||||||
{
|
|
||||||
//(e as MouseButtonEventArgs).Handled=true;
|
|
||||||
Window.Close();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
|
||||||
Triggers=
|
|
||||||
{
|
|
||||||
new Trigger(nameof(Panel.IsMouseOver), Relation.Me)
|
|
||||||
{
|
|
||||||
Setters =
|
|
||||||
{
|
|
||||||
{
|
{
|
||||||
nameof(Panel.Background),
|
{
|
||||||
hoverColor
|
nameof(Button.Click),
|
||||||
}
|
(s,e)=>
|
||||||
|
{
|
||||||
|
//(e as MouseButtonEventArgs).Handled = true;
|
||||||
|
Window.WindowState = WindowState.Normal;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Bindings =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
nameof(Border.Visibility),
|
||||||
|
nameof(Window.WindowState),
|
||||||
|
Window,
|
||||||
|
BindingMode.OneWay,
|
||||||
|
a => (WindowState)a == WindowState.Normal ? Visibility.Collapsed : Visibility.Visible
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Triggers=
|
||||||
|
{
|
||||||
|
new Trigger(nameof(Panel.IsMouseOver), Relation.Me)
|
||||||
|
{
|
||||||
|
Setters =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
nameof(Panel.Background),
|
||||||
|
hoverColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
new SystemButton
|
||||||
|
{
|
||||||
|
Name="close",
|
||||||
|
ToolTip="关闭",
|
||||||
|
Width = 30,
|
||||||
|
Height = "100%",
|
||||||
|
Content=new Panel{
|
||||||
|
Size=SizeField.Fill,
|
||||||
|
Children =
|
||||||
|
{
|
||||||
|
new Line
|
||||||
|
{
|
||||||
|
MarginTop=8,
|
||||||
|
MarginLeft=8,
|
||||||
|
StartPoint = new Point(1, 1),
|
||||||
|
EndPoint = new Point(14, 13),
|
||||||
|
StrokeStyle = "2",
|
||||||
|
IsAntiAlias=true,
|
||||||
|
//StrokeFill=color
|
||||||
|
Bindings = { { nameof(Line.StrokeFill), nameof(this.ControlBoxStroke), this } }
|
||||||
|
},
|
||||||
|
new Line
|
||||||
|
{
|
||||||
|
MarginTop=8,
|
||||||
|
MarginLeft=8,
|
||||||
|
StartPoint = new Point(14, 1),
|
||||||
|
EndPoint = new Point(1, 13),
|
||||||
|
StrokeStyle = "2",
|
||||||
|
IsAntiAlias=true,
|
||||||
|
//StrokeFill=color
|
||||||
|
Bindings = { { nameof(Line.StrokeFill), nameof(this.ControlBoxStroke), this } }
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Commands =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
nameof(Button.Click),
|
||||||
|
(s,e)=>
|
||||||
|
{
|
||||||
|
//(e as MouseButtonEventArgs).Handled=true;
|
||||||
|
Window.Close();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Triggers=
|
||||||
|
{
|
||||||
|
new Trigger(nameof(Panel.IsMouseOver), Relation.Me)
|
||||||
|
{
|
||||||
|
Setters =
|
||||||
|
{
|
||||||
|
{
|
||||||
|
nameof(Panel.Background),
|
||||||
|
hoverColor
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
if (Content != null)
|
if (Content != null)
|
||||||
{
|
{
|
||||||
grid.Children.Add(Content, 0, 1);
|
grid.Children.Add(Content, 0, 1);
|
||||||
|
104
CPF/CpfObject.cs
104
CPF/CpfObject.cs
@ -13,6 +13,7 @@ using CPF.Animation;
|
|||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Runtime.InteropServices;
|
using System.Runtime.InteropServices;
|
||||||
using System.Collections;
|
using System.Collections;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CPF
|
namespace CPF
|
||||||
{
|
{
|
||||||
@ -193,6 +194,10 @@ namespace CPF
|
|||||||
{
|
{
|
||||||
if (value.Command != null)
|
if (value.Command != null)
|
||||||
{
|
{
|
||||||
|
if (value.Command.AsyncAction != null)
|
||||||
|
{
|
||||||
|
Commands.Add(propertyName, value.Command.AsyncAction);
|
||||||
|
}
|
||||||
if (value.Command.Action != null)
|
if (value.Command.Action != null)
|
||||||
{
|
{
|
||||||
Commands.Add(propertyName, value.Command.Action);
|
Commands.Add(propertyName, value.Command.Action);
|
||||||
@ -1786,10 +1791,6 @@ namespace CPF
|
|||||||
/// <param name="eventName"></param>
|
/// <param name="eventName"></param>
|
||||||
public void RaiseEvent<TEventArgs>(in TEventArgs eventArgs, string eventName)
|
public void RaiseEvent<TEventArgs>(in TEventArgs eventArgs, string eventName)
|
||||||
{
|
{
|
||||||
//if (eventArgs is RoutedEventArgs routed)
|
|
||||||
//{
|
|
||||||
// routed.Sender = this;
|
|
||||||
//}
|
|
||||||
OnRaiseEvent(eventArgs, eventName);
|
OnRaiseEvent(eventArgs, eventName);
|
||||||
|
|
||||||
if (observers != null && eventArgs is EventArgs args)
|
if (observers != null && eventArgs is EventArgs args)
|
||||||
@ -1817,10 +1818,6 @@ namespace CPF
|
|||||||
v = item.Target.Target;
|
v = item.Target.Target;
|
||||||
objs.Add(v);
|
objs.Add(v);
|
||||||
}
|
}
|
||||||
//else if (item.Relation != null && this is UIElement)
|
|
||||||
//{
|
|
||||||
// objs.AddRange(item.Relation.Query(this as UIElement));
|
|
||||||
//}
|
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
v = CommandContext;
|
v = CommandContext;
|
||||||
@ -1856,14 +1853,6 @@ namespace CPF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//v.GetType().GetMethod(item.MethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance).FastInvoke(v, ps);
|
|
||||||
|
|
||||||
//var m = obj.GetType().GetMethod(item.MethodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
|
||||||
//if (m == null)
|
|
||||||
//{
|
|
||||||
// throw new Exception("未找到该方法 " + item.MethodName);
|
|
||||||
//}
|
|
||||||
//m.Invoke(obj, ps);
|
|
||||||
obj.Invoke(item.MethodName, ps);
|
obj.Invoke(item.MethodName, ps);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1882,6 +1871,89 @@ namespace CPF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task AsyncRaiseEvent<TEventArgs>(TEventArgs eventArgs, string eventName)
|
||||||
|
{
|
||||||
|
OnRaiseEvent(eventArgs, eventName);
|
||||||
|
|
||||||
|
if (observers != null && eventArgs is EventArgs args)
|
||||||
|
{
|
||||||
|
EventObserver<EventArgs, CpfObject> eventObserver = new EventObserver<EventArgs, CpfObject>(eventName, args, this);
|
||||||
|
foreach (var observer in observers)
|
||||||
|
{
|
||||||
|
observer.OnNext(eventObserver);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (commands != null)
|
||||||
|
{
|
||||||
|
List<Command> list;
|
||||||
|
if (commands.commands.TryGetValue(eventName, out list))
|
||||||
|
{
|
||||||
|
foreach (var item in list)
|
||||||
|
{
|
||||||
|
if (item.AsyncAction == null)
|
||||||
|
{
|
||||||
|
var objs = new List<object>();
|
||||||
|
object v = null;
|
||||||
|
if (item.Target != null)
|
||||||
|
{
|
||||||
|
v = item.Target.Target;
|
||||||
|
objs.Add(v);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
v = CommandContext;
|
||||||
|
if (v != null)
|
||||||
|
{
|
||||||
|
objs.Add(v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach (var obj in objs)
|
||||||
|
{
|
||||||
|
if (obj == null)
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
object[] ps = new object[item.Params == null ? 0 : item.Params.Length];
|
||||||
|
if (item.Params != null && item.Params.Length > 0)
|
||||||
|
{
|
||||||
|
//ps = item.Params;
|
||||||
|
item.Params.CopyTo(ps, 0);
|
||||||
|
for (int i = 0; i < ps.Length; i++)
|
||||||
|
{
|
||||||
|
var p = ps[i];
|
||||||
|
if (p is CommandParameter)
|
||||||
|
{
|
||||||
|
if ((CommandParameter)p == CommandParameter.EventArgs)
|
||||||
|
{
|
||||||
|
ps[i] = eventArgs;
|
||||||
|
}
|
||||||
|
else if ((CommandParameter)p == CommandParameter.EventSender)
|
||||||
|
{
|
||||||
|
ps[i] = this;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
await obj.AsyncInvoke(item.MethodName, ps);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//item.Action(this, eventArgs);
|
||||||
|
await item.AsyncAction(this, eventArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var handler = Events[eventName];
|
||||||
|
if (handler != null)
|
||||||
|
{
|
||||||
|
await handler.AsyncInvoke(this, eventArgs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
protected virtual void OnRaiseEvent<TEventArgs>(in TEventArgs eventArgs, string eventName)
|
protected virtual void OnRaiseEvent<TEventArgs>(in TEventArgs eventArgs, string eventName)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
9
CPF/Input/AsyncEventHandler.cs
Normal file
9
CPF/Input/AsyncEventHandler.cs
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
namespace CPF.Input
|
||||||
|
{
|
||||||
|
public delegate Task AsyncEventHandler<TEventArgs>(object sender, TEventArgs e);
|
||||||
|
}
|
@ -13,6 +13,7 @@ using CPF.Threading;
|
|||||||
using CPF.Controls;
|
using CPF.Controls;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Diagnostics;
|
||||||
|
|
||||||
namespace CPF
|
namespace CPF
|
||||||
{
|
{
|
||||||
@ -28,7 +29,7 @@ namespace CPF
|
|||||||
/// <param name="o"></param>
|
/// <param name="o"></param>
|
||||||
/// <param name="v"></param>
|
/// <param name="v"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static T Assign<T>(this T o,out T v)
|
public static T Assign<T>(this T o, out T v)
|
||||||
{
|
{
|
||||||
v = o;
|
v = o;
|
||||||
return o;
|
return o;
|
||||||
@ -652,6 +653,18 @@ namespace CPF
|
|||||||
}
|
}
|
||||||
return element;
|
return element;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static bool Or<T>(this T obj, params T[] ps)
|
||||||
|
{
|
||||||
|
foreach (var item in ps)
|
||||||
|
{
|
||||||
|
if (obj.Equals(item))
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
class Enumerable : IList
|
class Enumerable : IList
|
||||||
|
@ -6,6 +6,7 @@ using System.Reflection;
|
|||||||
using System.Linq.Expressions;
|
using System.Linq.Expressions;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
using System.Reflection.Emit;
|
using System.Reflection.Emit;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CPF.Reflection
|
namespace CPF.Reflection
|
||||||
{
|
{
|
||||||
@ -69,6 +70,7 @@ namespace CPF.Reflection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
static ConcurrentDictionary<Type, ConcurrentDictionary<string, InvokeHandler>> methods = new ConcurrentDictionary<Type, ConcurrentDictionary<string, InvokeHandler>>();
|
static ConcurrentDictionary<Type, ConcurrentDictionary<string, InvokeHandler>> methods = new ConcurrentDictionary<Type, ConcurrentDictionary<string, InvokeHandler>>();
|
||||||
|
static ConcurrentDictionary<Type, ConcurrentDictionary<string, AsyncInvokeHandler>> asyncMethods = new ConcurrentDictionary<Type, ConcurrentDictionary<string, AsyncInvokeHandler>>();
|
||||||
static KeyValuePair<Type, ConcurrentDictionary<string, InvokeHandler>>[] saveMethods;
|
static KeyValuePair<Type, ConcurrentDictionary<string, InvokeHandler>>[] saveMethods;
|
||||||
|
|
||||||
static ConcurrentDictionary<Type, ConcurrentDictionary<string, SetHandler<object>>> setValues = new ConcurrentDictionary<Type, ConcurrentDictionary<string, SetHandler<object>>>();
|
static ConcurrentDictionary<Type, ConcurrentDictionary<string, SetHandler<object>>> setValues = new ConcurrentDictionary<Type, ConcurrentDictionary<string, SetHandler<object>>>();
|
||||||
@ -106,6 +108,28 @@ namespace CPF.Reflection
|
|||||||
return fun(instance, parameters);
|
return fun(instance, parameters);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static async Task AsyncInvoke(this object instance, string methodName, params object[] parameters)
|
||||||
|
{
|
||||||
|
var type = instance.GetType();
|
||||||
|
|
||||||
|
if (!asyncMethods.TryGetValue(type, out var list))
|
||||||
|
{
|
||||||
|
list = new ConcurrentDictionary<string, AsyncInvokeHandler>();
|
||||||
|
asyncMethods.TryAdd(type, list);
|
||||||
|
}
|
||||||
|
if (!list.TryGetValue(methodName, out var fun))
|
||||||
|
{
|
||||||
|
var minfo = type.GetMethod(methodName, BindingFlags.Public | BindingFlags.NonPublic | BindingFlags.Instance);
|
||||||
|
if (minfo == null)
|
||||||
|
{
|
||||||
|
throw new Exception(type + "未找到方法:" + methodName);
|
||||||
|
}
|
||||||
|
fun = AsyncMethodCache.CreateInvokeDelegate(minfo);
|
||||||
|
list.TryAdd(methodName, fun);
|
||||||
|
}
|
||||||
|
await fun(instance, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 反射快速调用
|
/// 反射快速调用
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@ -115,10 +139,15 @@ namespace CPF.Reflection
|
|||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static object FastInvoke(this MethodInfo methodInfo, object instance, params object[] parameters)
|
public static object FastInvoke(this MethodInfo methodInfo, object instance, params object[] parameters)
|
||||||
{
|
{
|
||||||
//return FastReflectionCaches.MethodInvokerCache.Get(methodInfo).Invoke(instance, parameters);
|
|
||||||
return methodCache.Get(methodInfo).Invoke(instance, parameters);
|
return methodCache.Get(methodInfo).Invoke(instance, parameters);
|
||||||
}
|
}
|
||||||
|
public static async Task FastAsyncInvoke(this MethodInfo methodInfo, object instance, params object[] parameters)
|
||||||
|
{
|
||||||
|
await asyncMethodCache.Get(methodInfo).Invoke(instance, parameters);
|
||||||
|
}
|
||||||
|
|
||||||
static MethodCache methodCache = new MethodCache();
|
static MethodCache methodCache = new MethodCache();
|
||||||
|
static AsyncMethodCache asyncMethodCache = new AsyncMethodCache();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 快速动态设置对象的属性值
|
/// 快速动态设置对象的属性值
|
||||||
@ -369,7 +398,57 @@ namespace CPF.Reflection
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
class AsyncMethodCache : FastReflectionCache<MethodInfo, AsyncInvokeHandler>
|
||||||
|
{
|
||||||
|
protected override AsyncInvokeHandler Create(MethodInfo key)
|
||||||
|
{
|
||||||
|
return CreateInvokeDelegate(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static AsyncInvokeHandler CreateInvokeDelegate(MethodInfo methodInfo)
|
||||||
|
{
|
||||||
|
var instanceParameter = Expression.Parameter(typeof(object), "instance");
|
||||||
|
var parametersParameter = Expression.Parameter(typeof(object[]), "parameters");
|
||||||
|
|
||||||
|
var parameterExpressions = new List<Expression>();
|
||||||
|
var paramInfos = methodInfo.GetParameters();
|
||||||
|
for (int i = 0; i < paramInfos.Length; i++)
|
||||||
|
{
|
||||||
|
BinaryExpression valueObj = Expression.ArrayIndex(
|
||||||
|
parametersParameter, Expression.Constant(i));
|
||||||
|
UnaryExpression valueCast = Expression.Convert(
|
||||||
|
valueObj, paramInfos[i].ParameterType);
|
||||||
|
|
||||||
|
parameterExpressions.Add(valueCast);
|
||||||
|
}
|
||||||
|
|
||||||
|
var instanceCast = methodInfo.IsStatic ? null :
|
||||||
|
Expression.Convert(instanceParameter, methodInfo.ReflectedType);
|
||||||
|
|
||||||
|
var methodCall = Expression.Call(instanceCast, methodInfo, parameterExpressions);
|
||||||
|
|
||||||
|
if (methodCall.Type == typeof(void))
|
||||||
|
{
|
||||||
|
var lambda = Expression.Lambda<Action<object, object[]>>(
|
||||||
|
methodCall, instanceParameter, parametersParameter);
|
||||||
|
|
||||||
|
Action<object, object[]> execute = lambda.Compile();
|
||||||
|
return (instance, parameters) =>
|
||||||
|
{
|
||||||
|
execute(instance, parameters);
|
||||||
|
return null;
|
||||||
|
};
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var castMethodCall = Expression.Convert(methodCall, typeof(Task));
|
||||||
|
var lambda = Expression.Lambda<AsyncInvokeHandler>(
|
||||||
|
castMethodCall, instanceParameter, parametersParameter);
|
||||||
|
|
||||||
|
return lambda.Compile();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
class MethodCache : FastReflectionCache<MethodInfo, InvokeHandler>
|
class MethodCache : FastReflectionCache<MethodInfo, InvokeHandler>
|
||||||
{
|
{
|
||||||
protected override InvokeHandler Create(MethodInfo key)
|
protected override InvokeHandler Create(MethodInfo key)
|
||||||
@ -482,6 +561,8 @@ namespace CPF.Reflection
|
|||||||
//iLGenerator.Ret();
|
//iLGenerator.Ret();
|
||||||
//return (InvokeHandler)dynamicMethod.CreateDelegate(typeof(InvokeHandler));
|
//return (InvokeHandler)dynamicMethod.CreateDelegate(typeof(InvokeHandler));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
class PropertyGetCache : FastReflectionCache<PropertyInfo, GetHandler<object>>
|
class PropertyGetCache : FastReflectionCache<PropertyInfo, GetHandler<object>>
|
||||||
@ -578,5 +659,6 @@ namespace CPF.Reflection
|
|||||||
public delegate void SetHandler<T>(object target, T value);
|
public delegate void SetHandler<T>(object target, T value);
|
||||||
public delegate T GetHandler<T>(object target);
|
public delegate T GetHandler<T>(object target);
|
||||||
public delegate object InvokeHandler(object target, object[] paramters);
|
public delegate object InvokeHandler(object target, object[] paramters);
|
||||||
|
public delegate Task AsyncInvokeHandler(object target, object[] paramters);
|
||||||
public delegate void SetRefHandler<T, V>(ref T target, V value);
|
public delegate void SetRefHandler<T, V>(ref T target, V value);
|
||||||
}
|
}
|
||||||
|
@ -4,6 +4,7 @@ using System.Text;
|
|||||||
using CPF.Reflection;
|
using CPF.Reflection;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
namespace CPF
|
namespace CPF
|
||||||
{
|
{
|
||||||
@ -48,6 +49,24 @@ namespace CPF
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public async Task AsyncInvoke(object sender, object e)
|
||||||
|
{
|
||||||
|
if (delegates != null)
|
||||||
|
{
|
||||||
|
foreach (var item in delegates.ToArray())
|
||||||
|
{
|
||||||
|
if (item.reference.TryGetTarget(out var target) || item.method.IsStatic)
|
||||||
|
{
|
||||||
|
await item.method.FastAsyncInvoke(target, sender, e);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
delegates.Remove(item);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
public void Dispose()
|
public void Dispose()
|
||||||
{
|
{
|
||||||
delegates = null;
|
delegates = null;
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
|
|
||||||
Microsoft Visual Studio Solution File, Format Version 12.00
|
Microsoft Visual Studio Solution File, Format Version 12.00
|
||||||
# Visual Studio Version 16
|
# Visual Studio Version 17
|
||||||
VisualStudioVersion = 16.0.29324.140
|
VisualStudioVersion = 17.8.34316.72
|
||||||
MinimumVisualStudioVersion = 10.0.40219.1
|
MinimumVisualStudioVersion = 10.0.40219.1
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp1", "ConsoleApp1\ConsoleApp1.csproj", "{ABE4ED47-CB9F-4183-9CE3-65E3E521BE2A}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "ConsoleApp1", "ConsoleApp1\ConsoleApp1.csproj", "{ABE4ED47-CB9F-4183-9CE3-65E3E521BE2A}"
|
||||||
EndProject
|
EndProject
|
||||||
@ -59,12 +59,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "CPF.Demo", "CPF_Demo\CPF.De
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "蓝图重制版", "蓝图重制版\蓝图重制版.csproj", "{003E155A-8C40-41AF-A796-ED17E729E013}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "蓝图重制版", "蓝图重制版\蓝图重制版.csproj", "{003E155A-8C40-41AF-A796-ED17E729E013}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Toolkit", "Toolkit", "{28FB518C-2103-4772-A245-C5F1D40E1EF5}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CPF.Toolkit", "CPF.Toolkit\CPF.Toolkit.csproj", "{09C160EB-D2C3-42E5-82B3-7047CF87CE6C}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "CPF.Toolkit.Demo", "CPF.Toolkit.Demo\CPF.Toolkit.Demo.csproj", "{AEA7FF33-1621-4A0A-9C08-6C4CB10C76FF}"
|
||||||
|
EndProject
|
||||||
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "解决方案项", "解决方案项", "{C2358108-0235-4151-97F6-0283CFF98093}"
|
||||||
|
ProjectSection(SolutionItems) = preProject
|
||||||
|
Directory.Build.props = Directory.Build.props
|
||||||
|
EndProjectSection
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
|
||||||
Private\SharedVSIX\SharedVSIX.projitems*{db53e8d7-dfb6-48eb-a7b6-d1cf762acb9b}*SharedItemsImports = 4
|
|
||||||
Private\SharedVSIX\SharedVSIX.projitems*{df526631-d060-47f2-afd4-62c6cea2fe9a}*SharedItemsImports = 4
|
|
||||||
Private\SharedVSIX\SharedVSIX.projitems*{f34cffee-546f-490e-a76a-2792840b284d}*SharedItemsImports = 13
|
|
||||||
EndGlobalSection
|
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
Release|Any CPU = Release|Any CPU
|
Release|Any CPU = Release|Any CPU
|
||||||
@ -224,6 +230,18 @@ Global
|
|||||||
{003E155A-8C40-41AF-A796-ED17E729E013}.Release|Any CPU.Build.0 = Release|Any CPU
|
{003E155A-8C40-41AF-A796-ED17E729E013}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
{003E155A-8C40-41AF-A796-ED17E729E013}.类库d|Any CPU.ActiveCfg = 类库d|Any CPU
|
{003E155A-8C40-41AF-A796-ED17E729E013}.类库d|Any CPU.ActiveCfg = 类库d|Any CPU
|
||||||
{003E155A-8C40-41AF-A796-ED17E729E013}.类库d|Any CPU.Build.0 = 类库d|Any CPU
|
{003E155A-8C40-41AF-A796-ED17E729E013}.类库d|Any CPU.Build.0 = 类库d|Any CPU
|
||||||
|
{09C160EB-D2C3-42E5-82B3-7047CF87CE6C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{09C160EB-D2C3-42E5-82B3-7047CF87CE6C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{09C160EB-D2C3-42E5-82B3-7047CF87CE6C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{09C160EB-D2C3-42E5-82B3-7047CF87CE6C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{09C160EB-D2C3-42E5-82B3-7047CF87CE6C}.类库d|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{09C160EB-D2C3-42E5-82B3-7047CF87CE6C}.类库d|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AEA7FF33-1621-4A0A-9C08-6C4CB10C76FF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AEA7FF33-1621-4A0A-9C08-6C4CB10C76FF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{AEA7FF33-1621-4A0A-9C08-6C4CB10C76FF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{AEA7FF33-1621-4A0A-9C08-6C4CB10C76FF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{AEA7FF33-1621-4A0A-9C08-6C4CB10C76FF}.类库d|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{AEA7FF33-1621-4A0A-9C08-6C4CB10C76FF}.类库d|Any CPU.Build.0 = Debug|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@ -240,5 +258,15 @@ Global
|
|||||||
{1278A1BC-327D-4D13-AD04-C6FF2B680530} = {2B729C46-7592-425A-87E9-D769A94881F7}
|
{1278A1BC-327D-4D13-AD04-C6FF2B680530} = {2B729C46-7592-425A-87E9-D769A94881F7}
|
||||||
{F34CFFEE-546F-490E-A76A-2792840B284D} = {2B729C46-7592-425A-87E9-D769A94881F7}
|
{F34CFFEE-546F-490E-A76A-2792840B284D} = {2B729C46-7592-425A-87E9-D769A94881F7}
|
||||||
{DF526631-D060-47F2-AFD4-62C6CEA2FE9A} = {2B729C46-7592-425A-87E9-D769A94881F7}
|
{DF526631-D060-47F2-AFD4-62C6CEA2FE9A} = {2B729C46-7592-425A-87E9-D769A94881F7}
|
||||||
|
{09C160EB-D2C3-42E5-82B3-7047CF87CE6C} = {28FB518C-2103-4772-A245-C5F1D40E1EF5}
|
||||||
|
{AEA7FF33-1621-4A0A-9C08-6C4CB10C76FF} = {28FB518C-2103-4772-A245-C5F1D40E1EF5}
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
|
SolutionGuid = {E38AA5AA-8B93-40BD-8A5E-2E0D1538EB8D}
|
||||||
|
EndGlobalSection
|
||||||
|
GlobalSection(SharedMSBuildProjectFiles) = preSolution
|
||||||
|
Private\SharedVSIX\SharedVSIX.projitems*{db53e8d7-dfb6-48eb-a7b6-d1cf762acb9b}*SharedItemsImports = 4
|
||||||
|
Private\SharedVSIX\SharedVSIX.projitems*{df526631-d060-47f2-afd4-62c6cea2fe9a}*SharedItemsImports = 4
|
||||||
|
Private\SharedVSIX\SharedVSIX.projitems*{f34cffee-546f-490e-a76a-2792840b284d}*SharedItemsImports = 13
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
EndGlobal
|
EndGlobal
|
||||||
|
6
Directory.Build.props
Normal file
6
Directory.Build.props
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
|
<Project>
|
||||||
|
<PropertyGroup>
|
||||||
|
<LangVersion>preview</LangVersion>
|
||||||
|
</PropertyGroup>
|
||||||
|
</Project>
|
Loading…
x
Reference in New Issue
Block a user