
リポジトリREADMEは非常に基本的ですが、著者のREADMEが投稿したいくつかのブログ記事を参照して、あなたはそれを愛するでしょう、ナンセンスはあまり言わない、紹介ディレクトリ:
- アニメーションのカプセル化
https://blog.csdn.net/u010975589/article/details/95974854
- プロパティーシート
https://blog.csdn.net/u010975589/article/details/95970200
- メッセージのダイアログ
https://blog.csdn.net/u010975589/article/details/95985190
- WPFでMVCを使用する
https://blog.csdn.net/u010975589/article/details/100019431
- その他の機能の説明
https://blog.csdn.net/u010975589/article/details/103083605
詳細は以下の通り。
1. アニメーションのカプセル化
原文标题:示例:WPF中自定义StoryBoarService在代码中封装StoryBoard、Animation用于简化动画编写
原文链接:https://blog.csdn.net/u010975589/article/details/95974854
1.1目的:StoryBoardとAnimationをカプセル化してアニメーションの作成を簡素化する
1.2例:サンプル

説明:漸進的な非表示はWPFで最も一般的なアニメーションであり、上の画像はStoryBoar Serviceカプセル化された効果で、コード内で以下のコードを実行する限りです:
DoubleStoryboardEngine.Create(1, 0, 1, "Opacity").Start(element);
上記のシャットダウン効果は、以下のようにコマンドを定義できます:
public class CollapsedOfOpacityCommand : ICommand
{
public bool CanExecute(object parameter) => true;
public void Execute(object parameter)
{
if(parameter is UIElement element)
{
var engine = DoubleStoryboardEngine.Create(1, 0, 1, "Opacity");
engine.Start(element);
}
}
public event EventHandler CanExecuteChanged;
}
Xamlで次のコマンドを呼び出すと、徐々に非表示になる効果があります。
Command="{x:Static base:CommandService.CollapsedOfOpacityCommand}"
CommandParameter="{Binding RelativeSource={RelativeSource
AncestorType=GroupBox}}"
コマンド実行時に受信されたCommandParmeterは非表示になります。
アニメーション効果のコードは1文のコードで十分であり、コード内のアニメーションの面倒なコーディングプロセスを簡素化します。
DoubleStoryboardEngine.Create(1, 0, 1, "Opacity").Start(element);
1.3コードコード:
現時点ではDoubleAnimationのみを実装しており、他の型は後で実装される予定です。
1.3.1基本クラスの修正
/// <summary> 动画引擎基类 </summary>
public abstract class StoryboardEngineBase : IDisposable
{
protected Storyboard storyboard = new Storyboard();
public EventHandler CompletedEvent { get; set; }
public EasingFunctionBase Easing { get; set; } = EasingFunctionFactroy.PowerEase;
public PropertyPath PropertyPath { get; set; }
public Duration Duration { get; set; }
public void Dispose()
{
storyboard.Completed -= CompletedEvent;
}
public abstract StoryboardEngineBase Start(UIElement element);
public abstract StoryboardEngineBase Stop();
public StoryboardEngineBase(int second, string property)
{
this.PropertyPath = new PropertyPath(property);
this.Duration = new Duration(TimeSpan.FromSeconds(second));
}
}
/// <summary> 动画泛型引擎基类 </summary>
public abstract class StoryboardEngineBase<T> : StoryboardEngineBase
{
public StoryboardEngineBase(T from, T to, int second, string property) : base(second, property)
{
this.FromValue = from;
this.ToValue = to;
}
public T FromValue { get; set; }
public T ToValue { get; set; }
//public RepeatBehavior RepeatBehavior { get; set; };
}
1.3.2 DoubleStoryboardEngineのオープン拡張
/// <summary> DoubleAnimation动画引擎 </summary>
public class DoubleStoryboardEngine : StoryboardEngineBase<double>
{
public static DoubleStoryboardEngine Create(double from, double to, int second, string property)
{
return new DoubleStoryboardEngine(from, to, second, property);
}
public DoubleStoryboardEngine(double from, double to, int second, string property) : base(from, to, second, property)
{
}
public override StoryboardEngineBase Start(UIElement element)
{
// Do:时间线
DoubleAnimation animation = new DoubleAnimation(1, 0, this.Duration);
if (this.Easing != null)
animation.EasingFunction = this.Easing;
//if (this.RepeatBehavior != default(RepeatBehavior))
// animation.RepeatBehavior = (RepeatBehavior);
// Do:属性动画
storyboard.Children.Add(animation);
Storyboard.SetTarget(animation, element);
Storyboard.SetTargetProperty(animation, this.PropertyPath);
if (CompletedEvent != null)
storyboard.Completed += CompletedEvent;
storyboard.Begin();
return this;
}
public override StoryboardEngineBase Stop()
{
this.storyboard.Stop();
return this;
}
}
3.3過剰効果工場
/// <summary> 说明:https://docs.microsoft.com/zh-cn/dotnet/framework/wpf/graphics-multimedia/easing-functions </summary>
public static class EasingFunctionFactroy
{
/// <summary> PowerEase:创建加速和/或减速使用的公式的动画f(t) = tp其中 p 等于Power属性。 </summary>
public static PowerEase PowerEase { get; set; } = new PowerEase();
/// <summary> BackEase:略微收回动画的动作,然后再开始进行动画处理指示的路径中。 </summary>
public static BackEase BackEase { get; set; } = new BackEase();
/// <summary> ElasticEase:创建类似于弹簧来回直到静止的动画 </summary>
public static ElasticEase ElasticEase { get; set; } = new ElasticEase();
/// <summary> BounceEase:创建弹跳效果。 </summary>
public static BounceEase BounceEase { get; set; } = new BounceEase();
/// <summary> CircleEase:创建加速和/或减速使用循环函数的动画。 </summary>
public static CircleEase CircleEase { get; set; } = new CircleEase();
/// <summary> QuadraticEase:创建加速和/或减速使用的公式的动画f(t) = t2。 </summary>
public static QuadraticEase QuadraticEase { get; set; } = new QuadraticEase();
/// <summary> CubicEase:创建加速和/或减速使用的公式的动画f(t) = t3。 </summary>
public static CubicEase CubicEase { get; set; } = new CubicEase();
/// <summary> QuarticEase:创建加速和/或减速使用的公式的动画f(t) = t4。 </summary>
public static QuarticEase QuarticEase { get; set; } = new QuarticEase();
/// <summary> QuinticEase:创建加速和/或减速使用的公式的动画f(t) = t5。 </summary>
public static QuinticEase QuinticEase { get; set; } = new QuinticEase();
/// <summary> ExponentialEase:创建加速和/或减速使用指数公式的动画。 </summary>
public static ExponentialEase ExponentialEase { get; set; } = new ExponentialEase();
/// <summary> SineEase:创建加速和/或减速使用正弦公式的动画。 </summary>
public static SineEase SineEase { get; set; } = new SineEase();
}
3.4利用方法
/// <summary> 构造方法 </summary>
/// <param name="from"> 起始值</param>
/// <param name="to"> 结束值 </param>
/// <param name="second"> 间隔时间秒 </param>
/// <param name="property"> 修改属性名称 </param>
///
public static DoubleStoryboardEngine Create(double from, double to, int second, string property)
{
return new DoubleStoryboardEngine(from, to, second, property);
}
2. プロパティーシート
原文标题:示例:WPF开发的简单ObjectProperyForm用来绑定实体表单
原文链接:https://blog.csdn.net/u010975589/article/details/95970200
2.1目的:エンティティデータを直接バインドし、開発サイクルを簡素化するカスタムコントロール
2.2実現すること
- エンティティオブジェクトのバインド
- プロパティから属性名を表示する
- 特性による検证条件の追加
- String、Int、Double、DateTime、Boolなどの単純な型のDataTemplateテンプレートが実装されており、その他のテンプレートは拡張をサポートしている。
- その他のアップデート..。
2.3例:サンプル

エンティティの定義は以下の通り。
public class Student
{
[Display("姓名")]
[Required]
public string Name { get; set; }
[Display("班级")]
[Required]
public string Class { get; set; }
[Display("地址")]
[Required]
public string Address { get; set; }
[Display("邮箱")]
[Required]
public string Emall { get; set; }
[Display("可用")]
[Required]
public bool IsEnbled { get; set; }
[Display("时间")]
[Required]
public DateTime time { get; set; }
[Display("年龄")]
[Required]
public int Age { get; set; }
[Display("平均分")]
public double Score { get; set; }
[Display("电话号码")]
[Required]
[RegularExpression(@"^1[3|4|5|7|8][0-9]{9}$", ErrorMessage = "手机号码不合法!")]
public string Tel { get; set; }
}
- DisplayAttribute表示名を識別するために使用します。
- ResuiredAttribute:データが空にできないことを示す
- RgularExpression正規表現を参照してデータが一致するかどうかを検証
- その他の特性は後に更新されます。。。。。
アプリケーションの方法:
<UserControl.Resources>
<local:Student
x:Key="S.Student.HeBianGu"
Name="河边骨"
Address="四川省成都市高新区"
Class="四年级"
Emall="7777777777@QQ.com"
Age="33"
Score="99.99"
IsEnbled="True"
time="2019-09-09"
/>
</UserControl.Resources>
<wpfcontrollib:ObjectPropertyForm
Grid.Row="1"
Title="学生信息"
SelectObject="{StaticResource S.Student.HeBianGu}"
>
<base:Interaction.Behaviors>
<base:MouseDragElementBehavior ConstrainToParentBounds="True" />
<base:SelectZIndexElementBehavior /> </base:Interaction.Behaviors
></wpfcontrollib:ObjectPropertyForm>
2.4コードコード。
2.4.1反射による属性·特性の獲得
ObservableCollection<ObjectPropertyItem> PropertyItemSource
{
get { return (ObservableCollection<ObjectPropertyItem>)GetValue(PropertyItemSourceProperty); }
set { SetValue(PropertyItemSourceProperty, value); }
}
// Using a DependencyProperty as the backing store for MyProperty. This enables animation, styling, binding, etc...
public static readonly DependencyProperty PropertyItemSourceProperty =
DependencyProperty.Register("PropertyItemSource", typeof(ObservableCollection<ObjectPropertyItem>), typeof(ObjectPropertyForm), new PropertyMetadata(new ObservableCollection<ObjectPropertyItem>(), (d, e) =>
{
ObjectPropertyForm control = d as ObjectPropertyForm;
if (control == null) return;
ObservableCollection<ObjectPropertyItem> config = e.NewValue as ObservableCollection<ObjectPropertyItem>;
}));
void RefreshObject(object o)
{
Type type = o.GetType();
var propertys = type.GetProperties();
this.PropertyItemSource.Clear();
foreach (var item in propertys)
{
var from = ObjectPropertyFactory.Create(item, o);
this.PropertyItemSource.Add(from);
}
this.ItemsSource = this.PropertyItemSource;
}
2.4.2型ベースクラス、拡張など、ファクトリーメソッドの定義
/// <summary> 类型基类 </summary>
public class ObjectPropertyItem : NotifyPropertyChanged
{
public string Name { get; set; }
public PropertyInfo PropertyInfo { get; set; }
public object Obj { get; set; }
public ObjectPropertyItem(PropertyInfo property, object obj)
{
PropertyInfo = property;
var display = property.GetCustomAttribute<DisplayAttribute>();
Name = display == null ? property.Name : display.Name;
Obj = obj;
}
}
/// <summary> 泛型类型基类 </summary>
public class ObjectPropertyItem<T> : ObjectPropertyItem
{
private T _value;
/// <summary> 说明 </summary>
public T Value
{
get { return _value; }
set
{
this.Message = null;
// Do:检验数据有效性
if (Validations != null)
{
foreach (var item in Validations)
{
if (!item.IsValid(value))
{
this.Message = item.ErrorMessage;
}
}
}
_value = value;
RaisePropertyChanged("Value");
this.SetValue(value);
}
}
void SetValue(T value)
{
this.PropertyInfo.SetValue(Obj, value);
}
List<ValidationAttribute> Validations { get; }
public ObjectPropertyItem(PropertyInfo property, object obj) : base(property, obj)
{
Value = (T)property.GetValue(obj);
Validations = property.GetCustomAttributes<ValidationAttribute>()?.ToList();
if(Validations!=null&& Validations.Count>0)
{
this.Flag = "*";
}
}
private string _message;
/// <summary> 说明 </summary>
public string Message
{
get { return _message; }
set
{
_message = value;
RaisePropertyChanged("Message");
}
}
public string Flag { get; set; }
}
/// <summary> 字符串属性类型 </summary>
public class StringPropertyItem : ObjectPropertyItem<string>
{
public StringPropertyItem(PropertyInfo property, object obj) : base(property, obj)
{
}
}
/// <summary> 时间属性类型 </summary>
public class DateTimePropertyItem : ObjectPropertyItem<DateTime>
{
public DateTimePropertyItem(PropertyInfo property, object obj) : base(property, obj)
{
}
}
/// <summary> Double属性类型 </summary>
public class DoublePropertyItem : ObjectPropertyItem<double>
{
public DoublePropertyItem(PropertyInfo property, object obj) : base(property, obj)
{
}
}
/// <summary> Int属性类型 </summary>
public class IntPropertyItem : ObjectPropertyItem<int>
{
public IntPropertyItem(PropertyInfo property, object obj) : base(property, obj)
{
}
}
/// <summary> Bool属性类型 </summary>
public class BoolPropertyItem : ObjectPropertyItem<bool>
{
public BoolPropertyItem(PropertyInfo property, object obj) : base(property, obj)
{
}
}
工場の種類:
public class ObjectPropertyFactory
{
public static ObjectPropertyItem Create(PropertyInfo info, object obj)
{
if (info.PropertyType == typeof(int))
{
return new IntPropertyItem(info, obj);
}
else if (info.PropertyType == typeof(string))
{
return new StringPropertyItem(info, obj);
}
else if (info.PropertyType == typeof(DateTime))
{
return new DateTimePropertyItem(info, obj);
}
else if (info.PropertyType == typeof(double))
{
return new DoublePropertyItem(info, obj);
}
else if (info.PropertyType == typeof(bool))
{
return new BoolPropertyItem(info, obj);
}
return null;
}
}
4.3スタイルのテンプレート
<DataTemplate DataType="{x:Type base:StringPropertyItem}">
<Grid
Width="{Binding RelativeSource={RelativeSource AncestorType=local:ObjectPropertyForm},Path=Width-5}"
Height="35"
Margin="5,0"
>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock
Text="{Binding Name}"
FontSize="14"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
<TextBlock
Text="{Binding Flag}"
Grid.Column="1"
Margin="5,0"
FontSize="14"
Foreground="{DynamicResource S.Brush.Red.Notice}"
HorizontalAlignment="Right"
VerticalAlignment="Center"
/>
<local:FTextBox
Text="{Binding Value,UpdateSourceTrigger=PropertyChanged}"
Style="{DynamicResource DefaultTextBox}"
FontSize="14"
Width="Auto"
CaretBrush="Black"
Grid.Column="2"
Height="30"
base:ControlAttachProperty.FIcon=""
VerticalContentAlignment="Center"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
/>
<TextBlock
Text=""
Grid.Column="3"
Style="{DynamicResource FIcon }"
Foreground="{DynamicResource S.Brush.Red.Notice}"
Visibility="{Binding Message,Converter={x:Static base:XConverter.VisibilityWithOutStringConverter},ConverterParameter={x:Null},Mode=TwoWay}"
FontSize="14"
TextTrimming="CharacterEllipsis"
ToolTip="{Binding Message}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type base:BoolPropertyItem}">
<Grid
Width="{Binding RelativeSource={RelativeSource AncestorType=local:ObjectPropertyForm},Path=Width-5}"
Height="35"
Margin="5,0"
>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock
Text="{Binding Name}"
FontSize="14"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
<TextBlock
Text="{Binding Flag}"
Grid.Column="1"
Margin="5,0"
FontSize="14"
Foreground="{DynamicResource S.Brush.Red.Notice}"
HorizontalAlignment="Right"
VerticalAlignment="Center"
/>
<CheckBox
IsChecked="{Binding Value}"
FontSize="14"
Grid.Column="2"
Height="30"
VerticalContentAlignment="Center"
HorizontalAlignment="Left"
VerticalAlignment="Center"
/>
<TextBlock
Text=""
Grid.Column="3"
Style="{DynamicResource FIcon }"
Foreground="{DynamicResource S.Brush.Red.Notice}"
Visibility="{Binding Message,Converter={x:Static base:XConverter.VisibilityWithOutStringConverter},ConverterParameter={x:Null}}"
FontSize="14"
TextTrimming="CharacterEllipsis"
ToolTip="{Binding Message}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type base:DateTimePropertyItem}">
<Grid
Width="{Binding RelativeSource={RelativeSource AncestorType=local:ObjectPropertyForm},Path=Width-5}"
Height="35"
Margin="5,0"
>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock
Text="{Binding Name}"
FontSize="14"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
<TextBlock
Text="{Binding Flag}"
Grid.Column="1"
Margin="5,0"
FontSize="14"
Foreground="{DynamicResource S.Brush.Red.Notice}"
HorizontalAlignment="Right"
VerticalAlignment="Center"
/>
<DatePicker
SelectedDate="{Binding Value}"
FontSize="14"
Grid.Column="2"
Height="30"
VerticalContentAlignment="Center"
Width="Auto"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
/>
<TextBlock
Text=""
Grid.Column="3"
Style="{DynamicResource FIcon }"
Foreground="{DynamicResource S.Brush.Red.Notice}"
Visibility="{Binding Message,Converter={x:Static base:XConverter.VisibilityWithOutStringConverter},ConverterParameter={x:Null}}"
FontSize="14"
TextTrimming="CharacterEllipsis"
ToolTip="{Binding Message}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type base:IntPropertyItem}">
<Grid
Width="{Binding RelativeSource={RelativeSource AncestorType=local:ObjectPropertyForm},Path=Width-5}"
Height="35"
Margin="5,0"
>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock
Text="{Binding Name}"
FontSize="14"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
<TextBlock
Text="{Binding Flag}"
Grid.Column="1"
Margin="5,0"
FontSize="14"
Foreground="{DynamicResource S.Brush.Red.Notice}"
HorizontalAlignment="Right"
VerticalAlignment="Center"
/>
<Slider
Value="{Binding Value}"
FontSize="14"
Grid.Column="2"
Height="30"
VerticalContentAlignment="Center"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
/>
<TextBlock
Text=""
Grid.Column="3"
Style="{DynamicResource FIcon }"
Foreground="{DynamicResource S.Brush.Red.Notice}"
Visibility="{Binding Message,Converter={x:Static base:XConverter.VisibilityWithOutStringConverter},ConverterParameter={x:Null}}"
FontSize="14"
TextTrimming="CharacterEllipsis"
ToolTip="{Binding Message}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
</Grid>
</DataTemplate>
<DataTemplate DataType="{x:Type base:DoublePropertyItem}">
<Grid
Width="{Binding RelativeSource={RelativeSource AncestorType=local:ObjectPropertyForm},Path=Width-5}"
Height="35"
Margin="5,0"
>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock
Text="{Binding Name}"
FontSize="14"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
<TextBlock
Text="{Binding Flag}"
Grid.Column="1"
Margin="5,0"
FontSize="14"
Foreground="{DynamicResource S.Brush.Red.Notice}"
HorizontalAlignment="Right"
VerticalAlignment="Center"
/>
<Slider
Value="{Binding Value}"
FontSize="14"
Grid.Column="2"
Height="30"
VerticalContentAlignment="Center"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
/>
<TextBlock
Text=""
Grid.Column="3"
Style="{DynamicResource FIcon }"
Foreground="{DynamicResource S.Brush.Red.Notice}"
Visibility="{Binding Message,Converter={x:Static base:XConverter.VisibilityWithOutStringConverter},ConverterParameter={x:Null}}"
FontSize="14"
TextTrimming="CharacterEllipsis"
ToolTip="{Binding Message}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
</Grid>
</DataTemplate>
<style TargetType="local:ObjectPropertyForm">
<Setter Property="Background" Value="{DynamicResource S.Brush.TextBackgroud.Default}"/>
<Setter Property="BorderThickness" Value="0"/>
<!--<Setter Property="BorderBrush" Value="{x:Null}"/>-->
<Setter Property="HorizontalAlignment" Value="Stretch"/>
<Setter Property="VerticalAlignment" Value="Center"/>
<Setter Property="HorizontalContentAlignment" Value="Center"/>
<Setter Property="VerticalContentAlignment" Value="Center"/>
<!--<Setter Property="FocusVisualStyle" Value="{x:Null}"/>-->
<Setter Property="Padding" Value="0" />
<Setter Property="Width" Value="500" />
<Setter Property="Height" Value="Auto" />
<Setter Property="ItemsSource" Value="{Binding PropertyItemSource,Mode=TwoWay}" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel/>
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:ObjectPropertyForm">
<GroupBox Header="{TemplateBinding Title}">
<Border HorizontalAlignment="{TemplateBinding HorizontalAlignment}"
VerticalAlignment="{TemplateBinding VerticalAlignment}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<ItemsPresenter/>
</Border>
</GroupBox>
</ControlTemplate>
</Setter.Value>
</Setter>
</style>
4.4オープン拡張
2.4.4.1は、次のような拡張タイプを定義するだけです。
/// <summary> 字符串属性类型 </summary>
public class StringPropertyItem : ObjectPropertyItem<string>
{
public StringPropertyItem(PropertyInfo property, object obj) : base(property, obj)
{
}
}
2.4.4.2は以下のようなDataTmeplateを追加します。
<DataTemplate DataType="{x:Type base:StringPropertyItem}">
<Grid
Width="{Binding RelativeSource={RelativeSource AncestorType=local:ObjectPropertyForm},Path=Width-5}"
Height="35"
Margin="5,0"
>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="2*" />
<ColumnDefinition Width="30" />
</Grid.ColumnDefinitions>
<TextBlock
Text="{Binding Name}"
FontSize="14"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
<TextBlock
Text="{Binding Flag}"
Grid.Column="1"
Margin="5,0"
FontSize="14"
Foreground="{DynamicResource S.Brush.Red.Notice}"
HorizontalAlignment="Right"
VerticalAlignment="Center"
/>
<local:FTextBox
Text="{Binding Value,UpdateSourceTrigger=PropertyChanged}"
Style="{DynamicResource DefaultTextBox}"
FontSize="14"
Width="Auto"
CaretBrush="Black"
Grid.Column="2"
Height="30"
base:ControlAttachProperty.FIcon=""
VerticalContentAlignment="Center"
HorizontalAlignment="Stretch"
VerticalAlignment="Center"
/>
<TextBlock
Text=""
Grid.Column="3"
Style="{DynamicResource FIcon }"
Foreground="{DynamicResource S.Brush.Red.Notice}"
Visibility="{Binding Message,Converter={x:Static base:XConverter.VisibilityWithOutStringConverter},ConverterParameter={x:Null},Mode=TwoWay}"
FontSize="14"
TextTrimming="CharacterEllipsis"
ToolTip="{Binding Message}"
HorizontalAlignment="Center"
VerticalAlignment="Center"
/>
</Grid>
</DataTemplate>
3. メッセージのダイアログ
原文标题:示例:WPF中自定义MessageService应用DialogHost、Snackbar、NotifyIcon显示各种场景提示消息
原文链接:https://blog.csdn.net/u010975589/article/details/95985190
3.1目的:目的
異なるインタラクションシーンは異なるメッセージを提示する必要があり、異なるメッセージは異なる効果で表示する必要があり、DialogHost(ダイアログ)、NotifyIcon(メッセージプロンプト)、Snackbar(バブルメッセージ)を使用して様々なシーンプロンプトメッセージを表示し、ViewModelに適用します。
3.2実現すること
- 待機ダイアログ·ボックス
- OKダイアログ·ボックス
- “OK”と“キャンセル”ダイアログ·ボックス
- “パーセント進行状況”および“テキスト進行状況”ダイアログ·ボックス
- “バルーンプロンプトメッセージ”NotifyIcon
- プロンプトメッセージSnackbar
3.3例:サンプル

解説:
- ダイアログボックス:通常のダイアログボックスメッセージは上の図のように、待機ダイアログボックス、メッセージダイアログボックス、進行ダイアログボックス;
(現時点では上記のもののみがカプセル化されており、カスタムダイアログはUniversal Loadメソッドを呼び出すユーザーコントロールを作成するだけで済みます。
プロンプトメッセージ:進捗状況が正常に保存されると、プロンプトメッセージが必要になり、2秒が自動的に非表示になります(図の友情プロンプト部分のように)。
バブルメッセージ:プログラムが非表示または特定の状態にあるときにバブルプロンプトメッセージを適用する必要があります。
3.4コードコード。
[ViewModel("Loyout")]
class LoyoutViewModel : MvcViewModelBase
{
/// <summary> 命令通用方法 </summary>
protected override async void RelayMethod(object obj)
{
string command = obj?.ToString();
// Do:对话消息
if (command == "Button.ShowDialogMessage")
{
await MessageService.ShowSumitMessge("这是消息对话框?");
}
// Do:等待消息
else if (command == "Button.ShowWaittingMessge")
{
await MessageService.ShowWaittingMessge(() => Thread.Sleep(2000));
}
// Do:百分比进度对话框
else if (command == "Button.ShowPercentProgress")
{
Action<IPercentProgress> action = l =>
{
for (int i = 0; i < 100; i++)
{
l.Value = i;
Thread.Sleep(50);
}
Thread.Sleep(1000);
MessageService.ShowSnackMessageWithNotice("加载完成!");
};
await MessageService.ShowPercentProgress(action);
}
// Do:文本进度对话框
else if (command == "Button.ShowStringProgress")
{
Action<IStringProgress> action = l =>
{
for (int i = 1; i <= 100; i++)
{
l.MessageStr = $"正在提交当前页第{i}份数据,共100份";
Thread.Sleep(50);
}
Thread.Sleep(1000);
MessageService.ShowSnackMessageWithNotice("提交完成:成功100条,失败0条!");
};
await MessageService.ShowStringProgress(action);
}
// Do:确认取消对话框
else if (command == "Button.ShowResultMessge")
{
Action<object, DialogClosingEventArgs> action = (l, k) =>
{
if ((bool)k.Parameter)
{
MessageService.ShowSnackMessageWithNotice("你点击了取消");
}
else
{
MessageService.ShowSnackMessageWithNotice("你点击了确定");
}
};
MessageService.ShowResultMessge("确认要退出系统?", action);
}
// Do:提示消息
else if (command == "Button.ShowSnackMessage")
{
MessageService.ShowSnackMessageWithNotice("这是提示消息?");
}
// Do:气泡消息
else if (command == "Button.ShowNotifyMessage")
{
MessageService.ShowNotifyMessage("你有一条报警信息需要处理,请检查", "Notify By HeBianGu");
}
}
}
4. WPFでMVCを使用する
原文标题:封装:简要介绍自定义开发基于WPF的MVC框架
原文链接:https://blog.csdn.net/u010975589/article/details/100019431
4.1目的:目的
ASP.NET Coreを使用する場合、ページジャンプデータ処理の利便性としてMVCフレームワークを深く掘り下げますが、WPFには既製のMVCフレームワークがないようですので、MVCフレームワークのセットをカスタム開発し、使用中にフレームワークの利点を体験するために、MVVMベースのMVCフレームワークを簡単に紹介します。
4.2プロジェクトの構造

主要有三部分组成:Controller、View、ViewModel
ViewとViewModelは従来のWPFのMVVMパターンである。
違いは、ページジャンプがコントローラに適用されることです。コントローラの定義の例です。
4.3コントローラの定義と構造
4.3.1 LoyoutControllerの定義
[Route("Loyout")]
class LoyoutController : Controller
{
public LoyoutController(ShareViewModel shareViewModel) : base(shareViewModel)
{
}
public async Task<IActionResult> Center()
{
return View();
}
[Route("OverView/Button")]
public async Task<IActionResult> Mdi()
{
return View();
}
public async Task<IActionResult> Left()
{
return View();
}
public async Task<IActionResult> Right()
{
return View();
}
public async Task<IActionResult> Top()
{
return View();
}
public async Task<IActionResult> Bottom()
{
return View();
}
[Route("OverView/Toggle")]
public async Task<IActionResult> Toggle()
{
return View();
}
[Route("OverView/Carouse")]
public async Task<IActionResult> Carouse()
{
return View();
}
[Route("OverView/Evaluate")]
public async Task<IActionResult> Evaluate()
{
return View();
}
[Route("OverView/Expander")]
public async Task<IActionResult> Expander()
{
return View();
}
[Route("OverView/Gif")]
public async Task<IActionResult> Gif()
{
return View();
}
[Route("OverView/Message")]
public async Task<IActionResult> Message()
{
return View();
}
[Route("OverView/Upgrade")]
public async Task<IActionResult> Upgrade()
{
return View();
}
[Route("OverView/Property")]
public async Task<IActionResult> Property()
{
return View();
}
[Route("OverView/ProgressBar")]
public async Task<IActionResult> ProgressBar()
{
return View();
}
[Route("OverView/Slider")]
public async Task<IActionResult> Slider()
{
return View();
}
[Route("OverView/Tab")]
public async Task<IActionResult> Tab()
{
return View();
}
[Route("OverView/Tree")]
public async Task<IActionResult> Tree()
{
return View();
}
[Route("OverView/Observable")]
public async Task<IActionResult> Observable()
{
return View();
}
[Route("OverView/Brush")]
public async Task<IActionResult> Brush()
{
return View();
}
[Route("OverView/Shadow")]
public async Task<IActionResult> Shadow()
{
return View();
}
[Route("OverView/Button")]
public async Task<IActionResult> Button()
{
await MessageService.ShowWaittingMessge(() => Thread.Sleep(500));
this.ViewModel.ButtonContentText = DateTime.Now.ToString();
return View();
}
[Route("OverView/Grid")]
public async Task<IActionResult> Grid()
{
return View();
}
[Route("OverView/Combobox")]
public async Task<IActionResult> Combobox()
{
return View();
}
[Route("OverView")]
public async Task<IActionResult> OverView()
{
await MessageService.ShowWaittingMessge(() => Thread.Sleep(500));
MessageService.ShowSnackMessageWithNotice("OverView");
return View();
}
[Route("OverView/TextBox")]
public async Task<IActionResult> TextBox()
{
return View();
}
[Route("OverView/Book")]
public async Task<IActionResult> Book()
{
return View();
}
[Route("OverView/Xaml")]
public async Task<IActionResult> Xaml()
{
return View();
}
[Route("OverView/Dimension")]
public async Task<IActionResult> Dimension()
{
return View();
}
[Route("OverView/Geometry")]
public async Task<IActionResult> Geometry()
{
return View();
}
[Route("OverView/Panel")]
public async Task<IActionResult> Panel()
{
return View();
}
[Route("OverView/Transform3D")]
public async Task<IActionResult> Transform3D()
{
return View();
}
[Route("OverView/Drawer")]
public async Task<IActionResult> Drawer()
{
return View();
}
}
4.2フロントエンドのページ
以下のように、赤い部分はコントローラ内のジャンプするルートに対応します

如:选择了红色部分的 Button,首先会调用Button()方法,跳转到当前 Controller 对应的 View 文件加下的ButtonControl.xaml 页面
[Route("OverView/Button")]
public async Task<IActionResult> Button()
{
await MessageService.ShowWaittingMessge(() => Thread.Sleep(500);
this.ViewModel.ButtonContentText = DateTime.Now.ToString();
return View();
}
Buttonメソッドに、いくつかのビジネスロジックを記述することができます。例えば、現在のViewModelに対する追加削除変更などの通常操作で、現在のControllerメンバViewModelは内部カプセル化されたViewModelであり、ViewModelファイルの下の現在のControllerのViewModelに対応します。
3.3例

4.3.4左側のXamlリストは次のように定義できます。
<Grid>
<wpfcontrollib:LinkGroupExpander
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
x:Name="selectloyout"
SelectedLink="{Binding SelectLink,Mode=TwoWay}"
Command="{x:Static wpfcontrollib:DrawerHost.CloseDrawerCommand}"
CommandParameter="{x:Static Dock.Left}"
>
<wpfcontrollib:LinkActionGroup DisplayName="基础控件" Logo="">
<wpfcontrollib:LinkActionGroup.Links>
<wpfcontrollib:LinkAction
DisplayName="Button"
Logo=""
Controller="Loyout"
Action="Button"
/>
<wpfcontrollib:LinkAction
DisplayName="TextBox"
Logo=""
Controller="Loyout"
Action="TextBox"
/>
<wpfcontrollib:LinkAction
DisplayName="Combobox"
Logo=""
Controller="Loyout"
Action="Combobox"
/>
<wpfcontrollib:LinkAction
DisplayName="Toggle"
Logo=""
Controller="Loyout"
Action="Toggle"
/>
<wpfcontrollib:LinkAction
DisplayName="Evaluate"
Logo=""
Controller="Loyout"
Action="Evaluate"
/>
<wpfcontrollib:LinkAction
DisplayName="Expander"
Logo=""
Controller="Loyout"
Action="Expander"
/>
<wpfcontrollib:LinkAction
DisplayName="Gif"
Logo=""
Controller="Loyout"
Action="Gif"
/>
<wpfcontrollib:LinkAction
DisplayName="ProgressBar"
Logo=""
Controller="Loyout"
Action="ProgressBar"
/>
<wpfcontrollib:LinkAction
DisplayName="Slider"
Logo=""
Controller="Loyout"
Action="Slider"
/>
</wpfcontrollib:LinkActionGroup.Links>
</wpfcontrollib:LinkActionGroup>
<wpfcontrollib:LinkActionGroup DisplayName="布局控件" Logo="">
<wpfcontrollib:LinkActionGroup.Links>
<wpfcontrollib:LinkAction
DisplayName="MdiControl"
Logo=""
Controller="Loyout"
Action="Mdi"
/>
<wpfcontrollib:LinkAction
DisplayName="Carouse"
Logo=""
Controller="Loyout"
Action="Carouse"
/>
<wpfcontrollib:LinkAction
DisplayName="Tab"
Logo=""
Controller="Loyout"
Action="Tab"
/>
<wpfcontrollib:LinkAction
DisplayName="Tree"
Logo=""
Controller="Loyout"
Action="Tree"
/>
<wpfcontrollib:LinkAction
DisplayName="ObservableSource"
Logo=""
Controller="Loyout"
Action="Observable"
/>
<wpfcontrollib:LinkAction
DisplayName="Property"
Logo=""
Controller="Loyout"
Action="Property"
/>
<wpfcontrollib:LinkAction
DisplayName="Panel"
Logo=""
Controller="Loyout"
Action="Panel"
/>
</wpfcontrollib:LinkActionGroup.Links>
</wpfcontrollib:LinkActionGroup>
<wpfcontrollib:LinkActionGroup DisplayName="全局控件" Logo="">
<wpfcontrollib:LinkActionGroup.Links>
<wpfcontrollib:LinkAction
DisplayName="Message"
Logo=""
Controller="Loyout"
Action="Message"
/>
<wpfcontrollib:LinkAction
DisplayName="Upgrade"
Logo=""
Controller="Loyout"
Action="Upgrade"
/>
<wpfcontrollib:LinkAction
DisplayName="Drawer"
Logo=""
Controller="Loyout"
Action="Drawer"
/>
</wpfcontrollib:LinkActionGroup.Links>
</wpfcontrollib:LinkActionGroup>
<wpfcontrollib:LinkActionGroup DisplayName="全局样式" Logo="">
<wpfcontrollib:LinkActionGroup.Links>
<wpfcontrollib:LinkAction
DisplayName="Brush"
Logo=""
Controller="Loyout"
Action="Brush"
/>
<wpfcontrollib:LinkAction
DisplayName="Shadow"
Logo=""
Controller="Loyout"
Action="Shadow"
/>
</wpfcontrollib:LinkActionGroup.Links>
</wpfcontrollib:LinkActionGroup>
</wpfcontrollib:LinkGroupExpander>
</Grid>
LinkGroupExpanderコントロールを使用してLinkActionをカプセル化し、特定のページにジャンプするためにLinkActionのいくつかのプロパティを定義するだけで、ページをジャンプできます。
- コントローラープロパティ:どのコントローラーにジャンプするかを指定します。
- アクションプロパティ:どのメソッドにジャンプするかを示す。
- DisplayNameプロパティ:UIに表示される名前
- LogoプロパティUIに表示されるアイコン
ControllerのButtonメソッドのジャンプ設定は以下の通りです。
[Route("OverView/Button")]
public async Task<IActionResult> Button()
<wpfcontrollib:LinkAction
DisplayName="Button"
Logo=""
Controller="Loyout"
Action="Button"
/>
4.3.5コントローラベースクラスの定義ControllerBase
主要方法是IActionResult View([CallerMemberName] string name = ""),这个方法是 MVC 实现的核心功能,主要通过反射去动态加载程序集,加载项目结构中的 View、ViewModel 去生成 IActionResult 返回给主页面进行页面跳转,代码如下:
public abstract class ControllerBase : IController
{
protected virtual IActionResult View([CallerMemberName] string name = "")
{
var route = this.GetType().GetCustomAttributes(typeof(RouteAttribute), true).Cast<RouteAttribute>();
string controlName = null;
if (route.FirstOrDefault() == null)
{
controlName = this.GetType().Name;
}
else
{
controlName = route.FirstOrDefault().Name;
}
var ass = Assembly.GetEntryAssembly().GetName();
string path = $"/{ass.Name};component/View/{controlName}/{name}Control.xaml";
Uri uri = new Uri(path, UriKind.RelativeOrAbsolute);
var content = Application.Current.Dispatcher.Invoke(() =>
{
return Application.LoadComponent(uri);
});
ActionResult result = new ActionResult();
result.Uri = uri;
result.View = content as ContentControl;
Type type = Assembly.GetEntryAssembly().GetTypeOfMatch<NotifyPropertyChanged>(l => l.Name == controlName + "ViewModel");
result.ViewModel = ServiceRegistry.Instance.GetInstance(type);
Application.Current.Dispatcher.Invoke(() =>
{
(result.View as FrameworkElement).DataContext = result.ViewModel;
});
return result;
}
protected virtual IActionResult LinkAction([CallerMemberName] string name = "")
{
var route = this.GetType().GetCustomAttributes(typeof(RouteAttribute), true).Cast<RouteAttribute>();
string controlName = null;
if (route.FirstOrDefault() == null)
{
controlName = this.GetType().Name;
}
else
{
controlName = route.FirstOrDefault().Name;
}
var ass = Assembly.GetEntryAssembly().GetName();
string path = $"/{ass.Name};component/View/{controlName}/{name}Control.xaml";
Uri uri = new Uri(path, UriKind.RelativeOrAbsolute);
var content = Application.Current.Dispatcher.Invoke(() =>
{
return Application.LoadComponent(uri);
});
ActionResult result = new ActionResult();
result.Uri = uri;
result.View = content;
Type type = Assembly.GetEntryAssembly().GetTypeOfMatch<NotifyPropertyChanged>(l => l.Name == controlName + "ViewModel");
result.ViewModel = ServiceRegistry.Instance.GetInstance(type);
Application.Current.Dispatcher.Invoke(() =>
{
(result.View as FrameworkElement).DataContext = result.ViewModel;
});
return result;
}
}
Essbaseの説明
- Application.LoadComponent uri;を使用してビルドコントロールをロードする
- ViewModelベースクラスNotifyPropertyChangedを反映してViewModelを見つけ、Viewにバインドします。
- ViewとViewModelをIActionResultにカプセル化してメインページに読み込みます。
コントローラ内のメソッドの戻り値の型はasync Taskです
4.4ビュー内の構造と定義
プロジェクト内のビューの定義は、コントローラ内のメソッド対応に応じており、MVCでは構造[ビュー/Loyout]に厳密に従って定義されます。利点は、コード量を削減しながら、フォーマットを統一したコードをきれいにすることです。

赤いButtonControl.xamlは、ControllerのButtonメソッドがジャンプするページです。
4.5 ViewModelの定義と構造
LoyoutViewModelは、LoyoutControllerとView/Loyout 下のすべてのページに対応するViewModelです。

4.6 MVCアーキテクチャの実装は以下の通りです。

WPFにおけるMVCアプリケーションの簡単な例は以下のリンクからダウンロードできます。詳細と例は以下のリンクからダウンロードできます。
コードアドレスhttps//github.com/HeBianGu/WPF-ControlBase.git
Sqliteデータベースの別のアプリケーション例は以下のとおりです。
コードアドレスhttps//github.com/HeBianGu/WPF-ExplorerManager.git
5. その他の機能の説明
原文标题:示例:自定义WPF底层控件UI库 HeBianGu.General.WpfControlLib V2.0版本
原文链接:https://blog.csdn.net/u010975589/article/details/103083605
5.1目的:目的
いくつかのコントロールをカスタムコントロールライブラリにカプセル化し、迅速な開発を容易にします。
5.2機能の実現
- 常用基礎コントロールを基本的に実現し、通常のソフトウェアの迅速な開発を満足させる
- フレームワーク. NET Core 3.0 +、. NET FrameWork 4.5+を同時にサポート
5.3全体の概要

5.1ランディングページ

ログインページはLoginWindowBase基本クラスを継承し、Style=""を設定するだけです。
5.2メインページ

メインページは、LinkBase基本クラスを継承し、Style=""をするだけです。
メインウィンドウ全体はViewBoxでロードされ、ウィンドウをズームしたり、他の解像度デバイスに適用したりすると互換性があります。
5.3.3トピックの構成情報の保存

トピックの構成情報はApplicationBaseにカプセル化されており、終了時に設定された構成情報(トピックの色、フォントサイズなど)が自動的に保存されます。
** 要約:** このパターンを適用すると、再利用の目的を達成でき、共通部分を下部にカプセル化し、スタイルを変更する必要がある場合は、スタイルファイルを変更するか、依存属性を変更するだけで機能変更を満たすことができます。
5.4テーマ設定

ライトカラーのトピックの例を以下に示します。

暗いテーマの例は以下の通りです。

テーマ設定機能は、主に次のとおりです。
- テーマのメインカラーの設定
テーマ色は主に強調表示される部分を識別するために使用されます。現在は内蔵色を選択し、システムテーマ色を選択し、システムテーマ色を選択し、選択色をカスタマイズし、動的テーマを使用します。つまり、テーマを設定することは、指定時間ごとに自動的に変化します。
- テーマの設定
テーマは現在、明るいテーマ、暗いテーマ、灰色のテーマ、主な色の4つのテーマを実現しています
- フォントサイズの
フォントサイズは現在、LargeとSmallの2種類が組み込まれています。これらの2色は注入によってロードされます。つまり、プログラムのロード時に両方のフォントの初期値を設定できます。
- その他の構成
英語と英語を含み、標準行の高さを設定するなど、プログラムのロード時に初期化設定することができますが、ここでは紹介しません。
** 要約:** このデザインの目的は、審美的な外観が人によって異なり、カスタム構成を使用する方法は、変化するニーズにできるだけ多くを満たすことができます。
5.5その他の基本制御
5.1データの一覧

- aテーマフォントとテーマ設定に対応しています。後述するすべてのコントロールは、説明せずにテーマ設定を適用しています。
- bページあたりの記事数
1ページあたりに表示するバー数を設定できます
- C検索結果
指定した検索用語を含むエントリが表示されるまで、検索フィルタ条件を設定できます。
- Dページジャンプ
“前のページ”、“次のページ”、“最初のページ”、“最後のページ”、“指定ページ”
- eページ情報
のページがデータソースに属する第数から第数、データソースのエントリの
- F 2種類のグリッドページ
** まとめ:** 上記の機能はコントロールPagedDataGridにカプセル化されており、データソースをバインドするだけで上記の機能を実現できます。そのうち、印刷、エクスポートなどの機能は当面実現されていません。
5.2木の一覧

- aカテゴリーによるフィルタリングのサポート
上の図のように、指定したタイプを選択してリストをフィルタリングします。
- b条件による検索のサポート
上記のように、条件を入力して条件をフィルタできます。
** 要約:** データソースをTreeListViewコントロールにバインドします。
5.3その他の一般的な制御


- aダイアログ·ボックス
アプリケーションウィンドウではなく、オーバーレイ層のみを内蔵したダイアログボックスを使用することで、ウィンドウダイアログボックスによって引き起こされる問題の一部を回避できます。
- b対話ウィンドウ対話ウィンドウのカスタマイズ
相対的にシステム対話ウィンドウはより美しく、表示と非表示の効果を増加させ、注入方式を通じてボタンの個数と機能をカスタマイズすることができる
- c.メッセージの一覧
現在、ウィンドウ内表示とウィンドウシステム内表示の2つのモードがあり、ニーズに応じて表示方法をカスタマイズすることができます。

- dオンラインアップグレードの例は次のとおりです。

- eナビゲーションメニューの例は以下のとおりです。

- fその他の機能
ボタンコントロール、テキスト入力ボックスコントロール、ドロップダウンリストコントロール、数値コントロール、日付選択コントロール、バインディングをサポートするパスワードボックスコントロール、プログレスバーコントロール、ドラッグコントロール、ツリーコントロール、ページングコントロール、およびその他のカスタムコントロール。
上記のコントロールは、テーマの色、フォントサイズの切り替えなどを実現しており、一般的なソフトウェアの機能を満たしています。
全体構造が使用されるカスタムMvc 方式でロードされます。https//blog.csdn.net/u010975589/article/details/100019431
由于控件过多不做详细介绍,有兴趣的可以下载源码或加载nuget包
5.6使用方法は
Nugetパッケージを追加

説明:この例の一部は、サードパーティ製のフレームワークを参照しており、オープンソースは学習と参照にのみ使用され、商用目的ではありません。
このフレームワークを適用するその他の例:
- 示例:应用 WPF 开发的仿制 GitHub 客户端 UI 布局_HeBianGu 的博客-CSDN 博客
- 示例:应用 WPF 开发的仿制百度网盘客户端 UI 布局_HeBianGu 的博客-CSDN 博客_wpf 网盘
- 示例:应用 WPF 绘制轻量 Chart 图表之组合图效果预览_HeBianGu 的博客-CSDN 博客
- 封裝:WPF 基于 Vlc.DotNet.Wpf 封装的视频播放器_HeBianGu 的博客-CSDN 博客
- 示例:WPF 开发的 Image 图片控件,支持鸟撖图、滚轮放大、放大镜、圈定范围以及圈定范围放大等(示例一)_HeBianGu 的博客-CSDN 博客
5.7アドレスをダウンロード
GitHub 下载地址:GitHub - HeBianGu/WPF-ControlBase: Wpf 封装的自定义控件资源库
インストールパッケージサンプルのダウンロードアドレス
- 链接:https://pan.baidu.com/s/1y2UfDKIxoSOffj36gl7fOw
- 略称はL 2 IA。
アップデート:2019.1 2.16. NET Core 3.0追加
Core 3.0と. net 4.5をサポートソリューションアセンブリがロードできない場合は両方のフレームワークをインストールしてください