Compare commits

...

24 Commits

Author SHA1 Message Date
luxiaoqi
730bbcae25 1 2023-12-01 17:22:28 +08:00
luxiaoqi
36433178c2 1 2023-12-01 16:23:12 +08:00
luxiaoqi
0a12d33d15 Merge branch 'master' into Toolkit 2023-11-30 16:34:02 +08:00
luxiaoqi
5eb8c25799 mdi任务栏增加关闭功能 2023-11-30 16:33:03 +08:00
luxiaoqi
49b1ebcd5c 1 2023-11-30 11:12:09 +08:00
luxiaoqi
9ab836ff44 1 2023-11-30 09:43:34 +08:00
luxiaoqi
a1db3807ff mdi 2023-11-29 17:07:17 +08:00
luxiaoqi
6631fec5e6 Merge branch 'master' into Toolkit 2023-11-29 11:00:41 +08:00
luxiaoqi
807cbdf300 1 2023-11-29 11:00:06 +08:00
luxiaoqi
507e844275 1 2023-11-28 17:31:16 +08:00
Sakura
b79e63da71 mdi 2023-11-24 22:58:59 +08:00
Sakura
235e8ec59e 1 2023-11-24 20:01:57 +08:00
luxiaoqi
db457dac7b mdi 2023-11-24 17:31:24 +08:00
luxiaoqi
2004876770 1 2023-11-24 14:26:26 +08:00
Sakura
763a3893d6 1 2023-11-23 23:46:40 +08:00
luxiaoqi
a6fc04e737 button默认原生样式 2023-11-23 16:36:19 +08:00
luxiaoqi
bc5e6be81e Button.AsyncClick 2023-11-23 15:24:27 +08:00
luxiaoqi
c439a46e38 Button.AsyncClick 2023-11-23 15:20:43 +08:00
luxiaoqi
8decf9e554 1 2023-11-23 13:38:29 +08:00
luxiaoqi
40efe5292f 1 2023-11-23 09:57:32 +08:00
Sakura
313f8fd79b ILoading 2023-11-22 23:55:50 +08:00
Sakura
25ce5d78ba ViewManager 2023-11-22 21:28:58 +08:00
Sakura
2cd339388f viewmodel中增加close方法与onclose用于拦截关闭事件 2023-11-22 21:02:42 +08:00
luxiaoqi
f673ced43a toolkit 2023-11-22 17:30:26 +08:00
35 changed files with 2583 additions and 324 deletions

View File

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

View File

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

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

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

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

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

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

View 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,
}
}

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

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

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

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

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

View 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

Binary file not shown.

After

Width:  |  Height:  |  Size: 679 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 879 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 834 B

BIN
CPF.Toolkit/Images/warn.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 748 B

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

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

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

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

View File

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

View File

@ -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&lt;string, List&lt;Command&gt;&gt; /// KeyValuePair&lt;string, List&lt;Command&gt;&gt;
/// </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;
} }
} }

View File

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

View File

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

View File

@ -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>();

View File

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

View File

@ -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)
{ {

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

View File

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

View File

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

View File

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

View File

@ -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
View File

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<Project>
<PropertyGroup>
<LangVersion>preview</LangVersion>
</PropertyGroup>
</Project>