WPF中实现撤销功能的5个关键步骤,第4个多数人不知道

WPF入门_05命令 WPF中提供了一组已定义命令,命令包括以下类:ApplicationCommands、NavigationCommands、MediaCommands、EditingCommands 以及ComponentCommands。这些类提供诸如 Cut、BrowseBack、BrowseForward、Play、Stop 和 Pause 等命令(参照代码:CustomCommand.xaml,DataCommands.cs) 阅读详情

第一章:WPF命令与撤销机制概述

在WPF(Windows Presentation Foundation)应用程序开发中,命令(Commanding)是一种实现用户操作与业务逻辑解耦的重要机制。它允许开发者将界面元素的交互行为(如按钮点击)与执行逻辑分离,提升代码的可维护性与可测试性。

命令系统的核心组件

WPF命令模型主要依赖于 ICommand 接口,该接口定义了两个关键方法和一个事件:
  • Execute:执行关联的操作
  • CanExecute:判断命令是否可执行
  • CanExecuteChanged:当可执行状态变化时触发
常见的命令实现包括 RoutedCommand 和自定义的 RelayCommand(也称 DelegateCommand)。以下是典型的 RelayCommand 实现示例:
// 定义一个支持 Execute 和 CanExecute 的委托命令
public class RelayCommand : ICommand
{
    private readonly Action _execute;
    private readonly Func<bool> _canExecute;

    public RelayCommand(Action execute, Func<bool> canExecute = null)
    {
        _execute = execute;
        _canExecute = canExecute;
    }

    public bool CanExecute(object parameter) => _canExecute == null || _canExecute();

    public void Execute(object parameter) => _execute();

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }
}

撤销机制的基本设计思路

撤销(Undo)与重做(Redo)功能通常基于命令模式实现。每个用户操作被封装为一个命令对象,这些对象被推入一个历史栈中。通过管理栈的入栈与出栈操作,可实现状态回滚。 下表展示了典型撤销系统所需维护的数据结构:
数据结构用途说明
Undo Stack存储已执行但可撤销的命令
Redo Stack存储已被撤销但可重做的命令
Command Interface统一定义 Execute、Undo 方法
通过将命令模式与状态管理结合,WPF应用能够构建出响应式且具备操作历史追踪能力的用户界面。

第二章:ICommand接口基础与命令模式构建

2.1 理解ICommand接口的核心成员与执行逻辑

核心成员定义
ICommand 接口是 MVVM 模式中实现命令绑定的关键契约,其定义了两个核心方法:`Execute` 和 `CanExecute`。前者用于触发具体操作,后者决定命令是否可执行。
  1. Execute(object parameter):执行关联的业务逻辑,参数可选。
  2. CanExecute(object parameter):返回布尔值,控制命令的可用状态。
  3. CanExecuteChanged:事件通知 UI 更新命令状态。
执行逻辑分析
当界面触发命令时,WPF 首先调用 CanExecute 判断按钮是否启用,再执行 Execute 方法。开发者需手动触发 CanExecuteChanged 以刷新状态。
public event EventHandler CanExecuteChanged;
public void RaiseCanExecuteChanged() => CanExecuteChanged?.Invoke(this, EventArgs.Empty);
上述代码展示了事件触发机制,确保 UI 实时响应命令状态变化。

2.2 实现可撤销命令的Command基类设计

在命令模式中,实现可撤销操作的关键在于扩展基础 Command 接口,使其支持反向操作。通过引入 `undo()` 方法,每个命令对象不仅能执行动作,还能恢复其影响。
核心接口设计

public abstract class Command {
    public abstract void execute();
    public abstract void undo(); // 撤销上一步操作
}
该基类定义了所有命令必须实现的行为:`execute()` 执行具体逻辑,`undo()` 回滚该逻辑造成的影响。例如,文档编辑器中的“插入文本”命令,在 `undo()` 中应删除已插入的文本。
典型应用场景
  • 用户界面操作(如撤销/重做)
  • 事务性数据处理流程
  • 游戏中的动作回放机制
通过维护一个命令栈,系统可按顺序记录并回溯用户操作,从而实现多级撤销功能。

2.3 利用DelegateCommand封装UI操作与参数传递

在MVVM模式中,DelegateCommand 是实现命令绑定的核心工具,它将UI事件(如按钮点击)映射到ViewModel中的方法,实现界面与逻辑的解耦。
基本结构与参数支持
DelegateCommand 支持无参和带参两种形式。通过泛型参数,可接收任意类型的输入:
public ICommand SaveCommand { get; private set; }

// 构造函数中初始化
SaveCommand = new DelegateCommand<string>(ExecuteSave, CanSave);

private void ExecuteSave(string parameter)
{
    // parameter 来自XAML绑定的命令参数
    MessageBox.Show("保存内容:" + parameter);
}

private bool CanSave(string parameter) => !string.IsNullOrEmpty(parameter);
上述代码中,ExecuteSave 执行实际操作,CanSave 控制命令是否可用,实现动态启用/禁用UI元素。
优势与应用场景
  • 提升测试性:命令逻辑位于ViewModel,便于单元测试
  • 支持参数传递:通过CommandParameter向命令传值
  • 实现命令重用:多个控件可绑定同一命令实例

2.4 命令绑定在XAML中的最佳实践与调试技巧

确保命令的可访问性与生命周期管理
在XAML中绑定命令时,应确保命令实例在整个UI生命周期内有效。避免因ViewModel提前释放导致命令为null。
  • 使用RelayCommand或DelegateCommand封装执行逻辑
  • 确保DataContext正确设置,避免绑定断开
  • 在页面卸载时清理弱事件监听,防止内存泄漏
调试绑定失败的常见策略
当命令未触发时,优先检查输出窗口中的绑定错误日志。
<Button Content="保存" Command="{Binding SaveCommand}" />

若SaveCommand拼写错误或属性不可见(非public),将导致绑定失败。建议启用WPF跟踪:

<System.Diagnostics>
  <Switches>
    <add name="PresentationTraceSources.TraceLevel" value="High"/>
  </Switches>
</System.Diagnostics>
该配置可在输出窗口显示详细的绑定路径解析过程,便于定位源属性缺失问题。

2.5 命令启用/禁用状态管理与界面响应同步

在复杂前端应用中,命令的可用状态需与业务逻辑动态绑定,并实时反映在用户界面上。为实现这一目标,通常采用观察者模式或状态管理中间件来监听数据变化。
状态同步机制
通过响应式数据模型,当表单有效性、权限配置或后台数据状态发生变化时,自动触发命令(如“保存”、“提交”)的启用或禁用。

// 示例:基于Vue的命令状态控制
watch: {
  formValid(newVal) {
    this.$refs.submitButton.disabled = !newVal;
  }
}
上述代码监听表单验证状态,动态更新按钮的 disabled 属性,确保用户无法提交无效数据。
UI响应一致性策略
  • 使用统一的状态源(如Vuex或Pinia)集中管理命令状态
  • 通过指令或组件封装实现多处界面元素的同步控制

第三章:撤销服务的设计与状态管理

3.1 撤销堆栈(Undo Stack)的数据结构选择与实现

在实现撤销功能时,撤销堆栈是核心数据结构。通常采用**双栈法**:一个用于存储“撤销”操作的历史记录,另一个存储“重做”操作,确保操作可逆。
数据结构选型分析
  • 栈(Stack):符合后进先出(LIFO)语义,天然适合操作历史管理;
  • 命令模式封装:每条操作封装为命令对象,包含执行与回滚逻辑;
  • 内存优化考虑:限制栈深度,防止无限增长。
核心实现示例
type Command interface {
    Execute() error
    Undo() error
}

type UndoStack struct {
    history []Command
    redo    []Command
    maxLen  int
}

func (u *UndoStack) Push(cmd Command) {
    if err := cmd.Execute(); err != nil {
        return
    }
    u.history = append(u.history, cmd)
    u.redo = nil // 清空重做栈
    if len(u.history) > u.maxLen {
        u.history = u.history[1:]
    }
}

func (u *UndoStack) Undo() error {
    n := len(u.history)
    if n == 0 {
        return errors.New("nothing to undo")
    }
    cmd := u.history[n-1]
    u.history = u.history[:n-1]
    if err := cmd.Undo(); err != nil {
        return err
    }
    u.redo = append(u.redo, cmd)
    return nil
}
上述代码中,UndoStack 维护两个切片:history 存储已执行命令,redo 用于重做。每次撤销将命令从历史栈弹出并压入重做栈,实现状态可逆。

3.2 执行与撤销操作的对称性设计原则

在命令模式中,执行(execute)与撤销(undo)操作应遵循对称性设计原则,确保逻辑一致性与资源状态可逆。
对称性核心特征
  • 每个 execute 调用都应有对应的逆操作 undo
  • 操作前后对象状态应可预测且可恢复
  • 参数传递与资源管理需保持对称结构
代码实现示例
type Command interface {
    Execute() error
    Undo() error
}

type EditCommand struct {
    content string
    prevContent string
    doc *Document
}

func (c *EditCommand) Execute() error {
    c.prevContent = c.doc.GetContent()
    c.doc.SetContent(c.content)
    return nil
}

func (c *EditCommand) Undo() error {
    c.doc.SetContent(c.prevContent)
    return nil
}
上述代码中,Execute 保存当前状态并应用新值,Undo 则恢复至保存的状态,形成完全对称的操作路径。两个方法共享相同上下文(doc 和 prevContent),确保数据一致性。通过前置状态快照机制,实现精准回滚,体现命令模式中“动作-逆动作”的对等设计哲学。

3.3 结合ObservableCollection实现可视化操作历史

在WPF应用中,通过绑定`ObservableCollection`可轻松实现操作历史的动态展示。该集合在添加、移除或刷新项时自动通知UI更新,是实现可视化历史记录的理想选择。
数据同步机制
将操作历史封装为模型类,并绑定至`ObservableCollection`:
public class Operation
{
    public string Action { get; set; }
    public DateTime Timestamp { get; set; }
}
此模型记录操作类型与时间戳,便于在界面中按时间顺序展示。
实时更新UI
XAML中使用`ItemsControl`绑定集合:
<ItemsControl ItemsSource="{Binding OperationHistory}">
    <ItemsControl.ItemTemplate>
        <DataTemplate>
            <TextBlock Text="{Binding Action}" />
        </DataTemplate>
    </ItemsControl.ItemTemplate>
</ItemsControl>
当后台调用`OperationHistory.Add(new Operation{...})`时,UI自动刷新,无需手动重绘。
  • 支持MVVM模式下的双向数据流
  • 适用于撤销/重做、日志追踪等场景
  • 结合命令模式可完整记录用户行为

第四章:高级撤销场景与鲜为人知的关键细节

4.1 处理复合命令(Composite Command)的嵌套撤销

在实现复合命令时,嵌套撤销机制是保障操作原子性与可逆性的关键。当多个命令被封装为一个组合体时,需确保其撤销操作能按逆序逐层还原。
撤销栈结构设计
采用栈结构管理命令执行序列,每个复合命令内部维护子命令列表:

type CompositeCommand struct {
    commands []Command
}

func (c *CompositeCommand) Execute() {
    for _, cmd := range c.commands {
        cmd.Execute()
    }
}

func (c *CompositeCommand) Undo() {
    for i := len(c.commands) - 1; i >= 0; i-- {
        c.commands[i].Undo()
    }
}
上述代码中,Undo() 方法从末尾向前调用子命令的撤销方法,确保操作顺序正确回滚。
嵌套撤销的层级控制
  • 每层复合命令独立管理其子命令生命周期
  • 撤销时递归触发深层结构的逆向操作
  • 异常中断时保留部分已撤销状态,避免数据错乱

4.2 命令合并策略:减少冗余操作提升用户体验

在现代编辑器与协同系统的实现中,频繁的用户操作会生成大量细粒度命令,若不加优化,将导致性能下降和体验劣化。命令合并策略通过识别连续且可归约的操作,将其合并为单一复合命令,从而降低执行与撤销的开销。
合并条件与触发机制
常见的合并场景包括连续文本输入、批量样式修改等。系统需定义操作的可合并性,例如:
  • 相邻时间窗口内的同类操作
  • 作用于同一数据区域的更新
  • 无外部依赖或副作用的纯变更
代码实现示例
class CommandCombiner {
  combine(commands) {
    return commands.reduce((result, cmd) => {
      const last = result.at(-1);
      if (last && last.canMerge(cmd)) {
        last.merge(cmd); // 合并逻辑封装在命令对象内部
      } else {
        result.push(cmd);
      }
      return result;
    }, []);
  }
}
该函数遍历命令序列,依据canMerge判定是否可合并,并调用merge方法融合内容。此模式支持扩展,适用于富文本、表格等多种场景。

4.3 跨视图或ViewModel的全局撤销上下文共享

在复杂应用中,多个视图或ViewModel可能需要共享同一份撤销历史。为此,需构建一个全局可访问的撤销上下文服务。
撤销上下文服务设计
通过依赖注入将撤销管理器作为单例提供,确保所有组件引用同一实例。
class UndoManager {
  private commands: Command[] = [];
  private currentIndex = -1;

  execute(command: Command) {
    this.commands.splice(this.currentIndex + 1);
    this.commands.push(command);
    command.execute();
    this.currentIndex++;
  }

  undo() {
    if (this.currentIndex >= 0) {
      this.commands[this.currentIndex--].undo();
    }
  }
}
上述代码实现命令堆栈管理。execute 方法记录操作并推进指针,undo 恢复上一步。所有视图调用同一实例,实现跨模块撤销同步。
状态一致性保障
  • 使用观察者模式通知各视图更新“撤销/重做”按钮状态
  • 每次执行命令后触发 stateChanged 事件

4.4 捕获并恢复绑定数据的深层状态快照

在复杂的数据绑定系统中,捕获对象深层状态的快照是实现可逆操作的关键。为确保状态一致性,需递归遍历对象属性并序列化其结构。
快照生成策略
采用深拷贝技术结合代理监听,可在变更前保存原始状态。以下为基于 Go 的示例实现:

type Snapshot struct {
    Data map[string]interface{} `json:"data"`
}

func CaptureSnapshot(obj interface{}) *Snapshot {
    data := deepCopy(obj) // 递归复制嵌套结构
    return &Snapshot{Data: data}
}
上述代码通过 deepCopy 函数实现嵌套对象的完全隔离复制,避免引用共享导致的状态污染。
恢复机制设计
  • 维护历史快照栈,支持多级撤销
  • 恢复时触发响应式更新通知
  • 确保时间戳标记与版本控制同步

第五章:总结与架构优化建议

性能瓶颈的识别与应对策略
在高并发场景下,数据库连接池配置不当常成为系统瓶颈。通过监控工具定位到 PostgreSQL 连接等待时间上升后,调整 GORM 的连接池参数显著提升了响应速度:

db, err := gorm.Open(postgres.Open(dsn), &gorm.Config{})
sqlDB, _ := db.DB()
sqlDB.SetMaxOpenConns(100)
sqlDB.SetMaxIdleConns(10)
sqlDB.SetConnMaxLifetime(time.Hour)
微服务拆分的实际案例
某电商平台将单体架构中的订单、库存、支付模块拆分为独立服务,使用 gRPC 进行通信。拆分后,各服务可独立部署和扩展,发布频率提升 3 倍。关键指标对比:
指标拆分前拆分后
平均响应时间480ms190ms
部署时长22分钟6分钟
故障影响范围全站单一服务
缓存层设计优化
引入 Redis 作为多级缓存,结合本地缓存(如 bigcache)减少网络开销。针对热点商品信息,采用预加载机制与过期时间错峰策略,降低缓存雪崩风险。具体实现包括:
  • 使用一致性哈希分配缓存节点
  • 设置随机 TTL 避免集体失效
  • 通过消息队列异步更新缓存
[API Gateway] → [Service A] → [Redis Cluster] ↓ [MySQL RDS (Read Replica)]
WPF TextBox控件深度解析与实战技巧 TextBox控件是WPF中用于文本输入和编辑的基本控件,它继承自TextBoxBase类,提供了文本编辑的核心功能。它可以用于单行文本输入(如表单字段)、多行文本编辑(如注释或描述)等场景。TextBox的类层次结构如下:DependencyObjectVisualUIElementFrameworkElementControlTextBoxBaseTextBox 2. 基本属性与功能 TextBox控件的主要属性包括:下面是一个基本的TextBox控件示例: C#代码中操作TextBox: 3. 输入控 阅读详情

相关推荐

【WPF应用20】WPF 控件详解 - RepeatButton 重复按钮的使用

WPF 控件详解 - RepeatButton 重复按钮的使用

qq_35320456的博客 2129

WPF-DelegateCommand

接触WPF一段事件,已经是一个勉强合格的小白了。接下来的笔记是WPF MVVM模式下的Command 。一开始以为Command只有两种,一种是WPF常用的RelayCommand,另一种是待会的笔记—DelegateCommand,后来才发现还有第三种(果然是我知识范围不够):AttachbehaviorCommand。 经过测试发现RelayCommand比较适合WPF,因为RelayCommand下的CommandManager方法在silverlight,还是叫SL吧,在SL下面无法使用;而De

化学纤维 2538

WPF InkCanvas控件的详细使用教程

WPF InkCanvas 控件用于在应用程序中提供手写或绘图功能,支持用户用鼠标、触控设备或触控笔在画布上自由绘制。InkCanvas 是一个功能强大的控件,适用于绘图应用、签名板等场景。

weixin_39604653的博客 1940

wpf--->MVVM

MVVM适合制作企业级的应用 文章目录MVVM优势什么是MVVMModelView&ViewModel MVVM优势 团队层面:统一团队的思维方式和实现方法(特定的代码放在特定的位置) 架构层面:稳定,解耦合 代码层面:可读,可测,可替换 什么是MVVM MVVM= Model + View + ViewModel Model 现实中的抽象结果 View&ViewModel View=UI ViewModel=Model for View ViewModel与View沟通 .

qq_42069216的博客 878

wpf prism中的command应用

这是一个利用prim中的command的小例子,很简单适合初学者,可以把在对象中的通过修改模板添加的按钮绑定command后,通过命令,把当前对象传递到后台处理。

adas硬件_ADAS智能辅助驾驶系统硬件在环(HIL)测试之硬件介绍

这篇主要分享的是ADAS融合系统的HIL测试系统的硬件结构及其作用,其主要包括上位机、机柜、雷达模拟器系统、雷达暗箱系统以及视频暗箱。 上位机 上位机主要运行HIL测试系统的相关软件,测试人员所有的前期准备工作与测试操作均在上面进行,并监控测试结果,其通过网口实现与NI实时机的通信,上位机将VeriStand项目工程下载至NI实时机运行。机柜 机柜主要由可编程电源...

weixin_39580748的博客 2242

WPFCommand详解C#上位机学起来

WPF (Windows Presentation Foundation) 是一个微软的 UI 框架,用来构建 Windows 应用程序。在WPF中,我们可以使用Command来实现操作的绑定,可以通过Command将操作从UI界面中分离出来,使得代码更加清晰易懂。本文将详细介绍WPF中的Command,包括每种Command命令的实现方式,并给出具体实例。

Documentlv的博客 2702

【上海大学计算机组成原理实验报告】七、程序转移机制

学习实现程序转移的硬件机制//掌握堆栈寄存器的使用//手动方式实现子程序调用转移过程//手动方式实现子程序返回转移过程//编程实现`OUT`寄存器交替显示`11`和`55`//若要求`11`和`55`各显示`50`次后停机,应该如何修改程序?//根据实验指导书的相关内容,实验箱系统的程序转移硬件机制在于,当`LDPC`有效时,如果此时`DUBS`上的值就是转移的目标地址,则此目标地址被打入`PC`,从而实现程序的转移;若`LDPC`为`0`是附带条件的,就形成“条件转移”。

HackerKevon的博客 2474

记录 | WPF基础学习&MVVM例子讲解1

参考文章:《深入浅出WPF》系列高清视频教程 | 讲师:刘铁猛自己的感想。

技术小白=-=的博客 1243

C# Log4Net不输出日志的解决方法

log4net是一个流行的 .NET 日志框架,用于记录应用程序的日志信息。如果你在使用log4net。

精通搬砖,资深技术砖家,在软件开发,人工智能,设备开发等领域都有研究。商业合作&交流学习可私信联系。 1263

433M遥控器无线解码1527协议

433M遥控器无线解码1527协议,定时器轮询法

weixin_58595117的博客 1万+

WPF入门到跪下 第十一章 Prism(三)行为处理

Prism框架提供了类型,专门用于进行WPF中的行为处理。:的构造函数,创建对象。定义命令 xaml中绑定命令 以上做法就能实现最简单的命令了,缺点是无法进行命令状态检查。带参数的命令Prism框架中,命令的使用跟MVVMToolkit框架是类似的,命令的执行函数可以有参,也可以无参,具体用法如下: 二、命令的状态检查 Prism提供了三种命令状态检查方式可以向的构造函数中传入状态检查的委托函数。然后在合适的节点去调用对象的方法来执行状态检查函数。:的构造函数,创建对象。:调用对象的命令状态检查函数(构造时

SchuylerEX的博客 2686

从稀疏表示到低秩表示(一)

确定研究方向后一直在狂补理论,最近看了一些文章,有了些想法,顺便也总结了representation系列的文章,由于我刚接触,可能会有些不足,愿大家共同指正。 从稀疏表示到低秩表示系列文章包括如下内容: 一、 sparse representation 二、 一、 sparse representation 1  sparsity  一个线性表示解决的问题如下图所示:

彼岸花 3万+

揭秘WPF中ICommand撤销机制:5步构建可撤销的MVVM命令系统

掌握WPF命令(ICommand)实现撤销的完整方案,5步构建支持撤销重做的MVVM命令系统。适用于复杂表单编辑、图形操作等场景,通过封装可追踪命令提升用户体验。结构清晰、易于扩展,值得收藏。

ByteVein的博客 1037

Linux中断子系统(二)—— 通用框架处理

1、数据结构分析 (1)中断描述符结构structirq_desc: 1)打开CONFIG_SPARSE_IRQ宏(中断编号不连续),中断描述符以radix- tree来组织,用户在初始化时进行动态分配,然后再插入radix-tree中; 2)关闭CONFIG_SPARSE_IRQ宏(中断编号连续),中断描述符以数组的 形式组织,并且已经分配好; 3)不管哪种形式,最终都可以通过linuxirq号来找到对应的中断描述符; (2)stru...

weixin_38428439的博客 4871

深度学习、图像分类入门,从VGG16卷积神经网络开始

刚开始接触深度学习、卷积神经网络的时候非常懵逼,不知道从何入手,我觉得应该有一个进阶的过程,也就是说,理应有一些基本概念作为奠基石,让你有底气去完全理解一个庞大的卷积神经网络: 本文思路: 一、我认为学习卷积神经网络必须知道的几个概念: 1、卷积过程:   我们经常说卷积神经网络卷积神经网络,到底什么才是卷积?网络层卷积过程到底怎么实现?我们在这里借鉴了另一位博客大牛的动态图来给大

Errors_In_Life的博客 16万+

WPF实现简单C#代码编辑功能

通过本文的讲解,不仅可以掌握 WPF 实现简单代码编辑器的方法,还能深入理解RichTextBox富文本操作、正则表达式语法匹配、WPF 控件联动等核心知识点。在此基础上,可根据实际需求进行功能扩展,开发出更贴合开发场景的轻量级代码编辑工具。

让每一个想学习编程的人,都能学会,都能看懂,看了都有收获! 1213

宇树机器人G1二次开发:语音对话、打断与激活功能实现指南

宇树机器人G1是一款功能强大的四足机器人,其开放的SDK和API为开发者提供了广阔的二次开发空间。其中,语音交互是提升机器人智能化水平和用户体验的关键功能。本文将详细介绍如何在宇树机器人G1上进行二次开发,实现。语音打断允许用户在机器人说话时随时中断并输入新指令,这是提升交互自然度的关键功能。三大核心功能,帮助你构建更自然、更智能的人机交互系统。语音识别是将用户的语音输入转换为文本的过程。识别文本后,需要理解用户意图并生成回复。将文本回复转换为语音输出。

m0_52645558的博客 664

WPF快速入门系列(5)——深入解析WPF命令

一、引言   WPF命令相对来说是一个崭新的概念,因为命令对于之前的WinForm根本没有实现这个概念,但是这并不影响我们学习WPF命令,因为设计模式中有命令模式,关于命令模式可以参考我设计模式的博文:http://www.cnblogs.com/zhili/p/CommandPattern.html。命令模式的要旨在于把命令的发送者与命令的执行者之间的依赖关系分割开了。对此,WPF中的命令也是...

weixin_30905133的博客 2134

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

精雕软件(JDpaint) 5.5 绿色版

精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版精雕软件(JDpaint) 5.5 绿色版

基于WPF实现简单C#代码编辑功能的完整流程

首先定义 C# 关键字常量(用于语法匹配)、颜色常量(用于差异化着色),以及辅助变量,提升代码可维护性:12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970。

2501_94114815的博客 179

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

撤销和重做实现-第一部分(单对象状态变化)

撤销 重做 undo redo 设计模式 命令模式 备忘录模式

火柴盒 655

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

深入解析WPF命令模式

在开发过程中,自然少不了自定义命令来完成内置命令所没有提供的任务。下面通过一个例子来演示如何创建一个自定义命令。

kalvin_y_liu的博客 1345

Wpf画流程图项目,功能齐全(附源代码下载连接)

6、可以运行流程(开始、暂停、结束),底部有运行输出。3、点击图形节点拖拽可以连接其他图形节点。1、通过鼠标拖拽左边的工具到画布。7、代码注释详细,模块层次清晰。2、点击图形里面可以输入参数。

weixin_43474701的博客 2931
上一篇: 你真的会用C#元组吗?解构赋值的6种高阶用法曝光
下一篇: (C#泛型类型推断失效?)3步快速诊断并修复常见推断错误的终极指南
LiteCompile
博客等级 码龄1年 158粉丝 2022原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符  | 博主筛选后可见
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值