Artikelverzeichnis
Vorwort
Dieses Mal erklären wir den Komponentenentwicklungsprozess von WPF. Die Komponentenentwicklung ist eine Methode, die die Schwierigkeit unserer Seitenentwicklung erheblich reduzieren und die Codekopplung reduzieren kann. Dadurch können wir jede WPF-Schnittstelle zerlegen. Da ich Vue geschrieben habe, werde ich WPF gemäß der Logik von Vue in Komponenten entwickeln.
Column- und Gitee-Repository
Abhängigkeitseigenschaften
Um die Leistung zu verbessern, beschränkt WPF die Verwendung von Binding. Eigenschaften müssen im Voraus als abhängige Eigenschaften oder zusätzliche Eigenschaften registriert werden, um die Bindungssyntax verwenden zu können. Der Grund dafür ist, dass jedes bindbare Attribut Speicherplatz im Speicher freigeben muss. WPF kann standardmäßig nicht gebunden werden und muss aktiv deklariert werden.
Aus diesem Grund ist der Speicheraufwand von Elelctron, Fullter usw. so groß, weil sie auch Speicherplatz einrichten, der möglicherweise nutzlos ist.
Blog Park Detaillierte Erläuterung der WPF-Abhängigkeitseigenschaften
Praktischer Kampf: Verkleinern, Vollbild, Schließen-Taste
Hier erkläre ich den Unterschied zwischen Window und UserControl. Window ist das gesamte Fenster und UserControl ist das Steuerelement. Fenster ist für einige Methoden des Fensters verantwortlich, z. B. Ziehen, Vergrößern und Verkleinern. Da wir Komponenten entwickeln, müssen wir diesen Teil des Hauptfensters an die Unterkomponenten übergeben.
Kapselung von Abhängigkeitsattributoperationen
Werfen wir zunächst einen Blick auf meinen zusammenfassenden Blog.
Die WPF-Benutzersteuerung basiert auf der Zuweisung von Eigenschaften
Das Hauptfenster übergibt dies selbst an das TitleView-Titelsteuerelement
Da wir View und ViewModel entwickeln, haben alle Views nur die Funktion, Parameter zu übergeben und Abhängigkeitseigenschaften offenzulegen. Das eigentliche Geschäft wird von ViewModel erledigt.
Die Richtung, in die wir gehen, ist also
Haupt code
MainWindow.xmal
<Window x:Class="BlankApp1.Views.MainWindow"
......>
<!--需要主动设置名称,不然会Binding错误-->
<Window.DataContext>
<ViewModels:MainWindowViewModel x:Name="MainWindowViewModel" />
</Window.DataContext>
<DockPanel LastChildFill="True">
<!--其它代码-->
<Grid DockPanel.Dock="Top"
MouseLeftButtonDown="Grid_MouseLeftButtonDown"
Height="auto">
<!--手动指定DataContext-->
<Views:TitleView MainWindow="{Binding MainWindow, ElementName=MainWindowViewModel}" />
</Grid>
</DockPanel>
</Window>
MainWindow.cs
public partial class MainWindow : Window
{
public MainWindowViewModel ViewModel {
get; set; }
public MainWindow()
{
InitializeComponent();
//重定向ViewModel
ViewModel = (MainWindowViewModel)DataContext;
ViewModel.MainWindow = this;
}
}
Kapselung der Abhängigkeitseigenschaftsmethode
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace BlankApp1.Utils
{
public class MyWpfExtension<View> where View : class
{
/// <summary>
/// 简化依赖注入代码
/// </summary>
/// <typeparam name="View"></typeparam>
/// <typeparam name="Value"></typeparam>
/// <param name="name"></param>
/// <param name="action"></param>
/// <returns></returns>
public DependencyProperty DependencyPropertySet<Value>(string name, Action<View, Value> action)
{
var res = DependencyProperty.Register(name, typeof(Value), typeof(View), new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.BindsTwoWayByDefault,
new PropertyChangedCallback((item, res) =>
{
var model = item as View;
var value = (Value)res.NewValue;
if (model != null)
{
action(model, value);
}
else
{
throw new Exception("model value is null");
}
})));
return res;
}
}
}
TitleView.cs
namespace BlankApp1.Views
{
/// <summary>
/// TitleView.xaml 的交互逻辑
/// </summary>
public partial class TitleView : UserControl
{
//这个只是为了代码提示,不涉及逻辑
public MainWindow MainWindow {
get; set; }
//初始化依赖属性构造器
public static readonly MyWpfExtension<TitleView> MyWpfExtension = new MyWpfExtension<TitleView>();
//这个是简化后的依赖属性
public static readonly DependencyProperty MainWindowProperty =
MyWpfExtension.DependencyPropertySet<MainWindow>("MainWindow", (view, value) =>
{
//通过依赖属性来获取MainWindow的对象
view.TitileViewModel.MainWindow = value;
});
/// <summary>
/// DataContext的数据
/// </summary>
public TitileViewModel TitileViewModel {
get; set; }
public TitleView()
{
InitializeComponent();
//拿到DataContext数据重定向
TitileViewModel = (TitileViewModel)DataContext;
}
}
}
TitleViewModel
using BlankApp1.Models;
using BlankApp1.Views;
using CommunityToolkit.Mvvm.ComponentModel;
using CommunityToolkit.Mvvm.Input;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
namespace BlankApp1.ViewModels
{
public partial class TitileViewModel:ObservableObject
{
public RelayCommand CloseWindow {
get; set; }
public RelayCommand MaxOrNormalWindow {
get; set; }
public RelayCommand MiniWindow {
get; set; }
public MainWindow MainWindow {
get; set; }
public TitileViewModel() {
//.......其它代码
CloseWindow = new RelayCommand(() => {
MainWindow.Close();
Debug.WriteLine("关闭窗口");
});
MaxOrNormalWindow = new RelayCommand(() => {
if(MainWindow.WindowState == WindowState.Normal)
{
MainWindow.WindowState = WindowState.Maximized;
MainWindow.MaxHeight = SystemParameters.MaximizedPrimaryScreenHeight;
MainWindow.MaxWidth = SystemParameters.MaximizedPrimaryScreenWidth;
}
else
{
MainWindow.WindowState = WindowState.Normal;
}
Debug.WriteLine("最大化或正常窗口");
});
MiniWindow = new RelayCommand(() => {
MainWindow.WindowState = WindowState.Minimized;
Debug.WriteLine("缩小窗口");
});
}
}
}
TitleViewModel
Es ist nur ein verbindliches Schaltflächenereignis, ich werde es nicht loslassen
Den detaillierten Code finden Sie in meiner Gitee-Lageradresse