This commit is contained in:
Sakura
2024-01-25 22:35:00 +08:00
parent e85766dcc5
commit af2e243f07
16 changed files with 997 additions and 9 deletions

View File

@@ -0,0 +1,15 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<TargetFramework>netstandard2.0</TargetFramework>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="PropertyChanged.Fody" Version="4.1.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\CPF\CPF.csproj" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,3 @@
<Weavers xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:noNamespaceSchemaLocation="FodyWeavers.xsd">
<PropertyChanged />
</Weavers>

View File

@@ -0,0 +1,74 @@
<?xml version="1.0" encoding="utf-8"?>
<xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
<!-- This file was generated by Fody. Manual changes to this file will be lost when your project is rebuilt. -->
<xs:element name="Weavers">
<xs:complexType>
<xs:all>
<xs:element name="PropertyChanged" minOccurs="0" maxOccurs="1">
<xs:complexType>
<xs:attribute name="InjectOnPropertyNameChanged" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the On_PropertyName_Changed feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="TriggerDependentProperties" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the Dependent properties feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="EnableIsChangedProperty" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if the IsChanged property feature is enabled.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="EventInvokerNames" type="xs:string">
<xs:annotation>
<xs:documentation>Used to change the name of the method that fires the notify event. This is a string that accepts multiple values in a comma separated form.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CheckForEquality" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should be inserted. If false, equality checking will be disabled for the project.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="CheckForEqualityUsingBaseEquals" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should use the Equals method resolved from the base class.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="UseStaticEqualsFromBase" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to control if equality checks should use the static Equals method resolved from the base class.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="SuppressWarnings" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to turn off build warnings from this weaver.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="SuppressOnPropertyNameChangedWarning" type="xs:boolean">
<xs:annotation>
<xs:documentation>Used to turn off build warnings about mismatched On_PropertyName_Changed methods.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:all>
<xs:attribute name="VerifyAssembly" type="xs:boolean">
<xs:annotation>
<xs:documentation>'true' to run assembly verification (PEVerify) on the target assembly after all weavers have been executed.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="VerifyIgnoreCodes" type="xs:string">
<xs:annotation>
<xs:documentation>A comma-separated list of error codes that can be safely ignored in assembly verification.</xs:documentation>
</xs:annotation>
</xs:attribute>
<xs:attribute name="GenerateXsd" type="xs:boolean">
<xs:annotation>
<xs:documentation>'false' to turn off automatic generation of the XML Schema file.</xs:documentation>
</xs:annotation>
</xs:attribute>
</xs:complexType>
</xs:element>
</xs:schema>

14
CPF.Toolkit/ICloseable.cs Normal file
View File

@@ -0,0 +1,14 @@
using CPF.Controls;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
namespace CPF.Toolkit
{
public interface ICloseable
{
event EventHandler<ClosingEventArgs> Closable;
void OnClosable(ClosingEventArgs e);
}
}

11
CPF.Toolkit/ILoaded.cs Normal file
View File

@@ -0,0 +1,11 @@
using System;
using System.Collections.Generic;
using System.Text;
namespace CPF.Toolkit
{
public interface ILoaded
{
void OnLoaded();
}
}

View File

@@ -0,0 +1,80 @@
using CPF.Controls;
using System;
using System.Collections.Generic;
using System.Text;
namespace CPF.Toolkit
{
public class ViewBehavior : Behavior<Window>
{
protected override void OnBehaviorTo(Window window)
{
window.PropertyChanged += Window_PropertyChanged;
window.Loaded += Window_Loaded;
window.Closing += Window_Closing;
window.Closed += Window_Closed;
base.OnBehaviorTo(window);
}
protected override void OnDetachingFrom(Window window)
{
window.PropertyChanged -= Window_PropertyChanged;
window.Loaded -= Window_Loaded;
window.Closing -= Window_Closing;
window.Closed -= Window_Closed;
base.OnDetachingFrom(window);
}
private void Window_Closed(object sender, EventArgs e)
{
var window = (Window)sender;
if (window.DataContext is IDisposable disposable)
{
disposable.Dispose();
}
}
private void Window_Closing(object sender, ClosingEventArgs e)
{
var window = (Window)sender;
if (window.DataContext is ICloseable closeable)
{
closeable.OnClosable(e);
}
}
private void Window_Loaded(object sender, EventArgs e)
{
var window = (Window)sender;
if (window.DataContext is ILoaded loaded)
{
loaded.OnLoaded();
}
}
private void Window_PropertyChanged(object sender, CPFPropertyChangedEventArgs e)
{
switch (e.PropertyName)
{
case nameof(DataContext):
{
if (e.NewValue is ICloseable closeable)
{
closeable.Closable -= Closeable_Closable;
closeable.Closable += Closeable_Closable;
}
}
break;
}
void Closeable_Closable(object _, ClosingEventArgs ee)
{
if (!ee.Cancel)
{
var window = (Window)sender;
window.Close();
}
}
}
}
}

View File

@@ -0,0 +1,33 @@
using CPF.Controls;
using System;
using System.Collections.Generic;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Text;
namespace CPF.Toolkit
{
public class ViewModelBase : INotifyPropertyChanged, ILoaded, IDisposable, ICloseable
{
WeakEventHandlerList events = new WeakEventHandlerList();
event EventHandler<ClosingEventArgs> ICloseable.Closable { add => AddHandler(value); remove => RemoveHandler(value); }
public virtual void Dispose() { }
void ICloseable.OnClosable(ClosingEventArgs e) => this.OnClosing(e);
void ILoaded.OnLoaded() => this.OnLoaded();
protected virtual void OnLoaded() { }
protected void Close() => this.RaiseEvent(new ClosingEventArgs(), nameof(ICloseable.Closable));
protected virtual void OnClosing(ClosingEventArgs e) { }
public event PropertyChangedEventHandler PropertyChanged;
protected void AddHandler(Delegate handler, [CallerMemberName] string eventName = null) => events.AddHandler(handler, eventName);
protected void RemoveHandler(Delegate handler, [CallerMemberName] string eventName = null) => events.RemoveHandler(handler, eventName);
protected void RaiseEvent<TEventArgs>(in TEventArgs eventArgs, string eventName) => events[eventName]?.Invoke(this, eventArgs);
}
}