WPF框架---MvvmLight介紹

目錄

1. MvvmLight 框架準備

2. MvvmLight 中的相關基類

3. MvvmLight 中的數據綁定與通知

a. 核心功能

b. 關鍵方法與屬性

c. 完整示例

d. 高級用法

4. MvvmLight 中的命令對象

a. 命令對象的作用

b. 核心接口:ICommand

c. MvvmLight 中的 RelayCommand

d. 動態更新命令的可執行狀態

e. 高級用法

5. Messenger 對象使用

a. Messenger 的核心作用

b. MvvmLight 中的 Messenger 實現

c. 基本使用場景

d. 高級用法

6. DispatcherHelper 對象使用

7. SimpleIoc 對象使用

a. SimpleIoc 的核心作用

b. 核心方法與屬性

c. 基本使用步驟

d. 高級用法

e. 與 ViewModelLocator 結合使用


1. MvvmLight 框架準備

  • 作用: 快速搭建 MVVM 架構的應用程序,簡化數據綁定、命令和消息傳遞。
  • 步驟: 通過 NuGet 安裝 MvvmLightLibs 包。

2. MvvmLight 中的相關基類

  • 核心基類:
    • ViewModelBase: ViewModel 基類,實現 INotifyPropertyChanged
public class MainViewModel : ViewModelBase
{private string _name;public string Name{get => _name;set => Set(ref _name, value); // 自動觸發 PropertyChanged}
}
    • ObservableObject: 輕量級可觀察對象。
    • RelayCommand: 命令對象基類。

3. MvvmLight 中的數據綁定與通知

a. 核心功能

ViewModelBase 繼承自 ObservableObject,并實現了 INotifyPropertyChanged 接口,主要負責:

  • 屬性變更通知:當 ViewModel 的某個屬性值發生變化時,自動通知 UI 更新。
  • 簡化代碼:通過 Set 方法簡化屬性定義,避免手動觸發 PropertyChanged 事件。
  • 設計模式支持:提供靜態屬性 IsInDesignMode,用于區分代碼是在設計時(如 Visual Studio 設計器)還是運行時執行。
b. 關鍵方法與屬性

(1) Set<T>(ref T field, T value, [CallerMemberName] string propertyName = null)

  • 作用:在屬性的 set 方法中調用此方法,自動比較新舊值,若不同則更新字段并觸發 PropertyChanged 事件。
  • 示例
private string _name;
public string Name
{get => _name;set => Set(ref _name, value); // 自動觸發通知
}

(2)RaisePropertyChanged(string propertyName)

  • 作用:手動觸發某個屬性的 PropertyChanged 事件。
  • 場景:當某個屬性的值依賴于其他屬性時,手動通知 UI 更新。
public string FullName => $"{FirstName} {LastName}";private string _firstName;
public string FirstName
{get => _firstName;set{Set(ref _firstName, value);RaisePropertyChanged(nameof(FullName)); // 通知 FullName 屬性變化}
}

(3) IsInDesignMode

  • 作用:靜態屬性,判斷當前代碼是否在設計器(如 Visual Studio 或 Blend)中運行。
  • 用途:在設計時提供假數據,避免調用真實服務或數據庫。
public class MainViewModel : ViewModelBase
{public MainViewModel(){if (IsInDesignMode)Name = "Design Mode Sample"; // 設計器顯示假數據elseLoadRealData(); // 運行時加載真實數據}
}
c. 完整示例
using GalaSoft.MvvmLight;public class UserViewModel : ViewModelBase
{private string _userName;private int _age;public string UserName{get => _userName;set => Set(ref _userName, value);}public int Age{get => _age;set => Set(ref _age, value);}// 計算屬性(依賴其他屬性)public string UserInfo => $"{UserName} (Age: {Age})";// 當 UserName 或 Age 變化時,手動通知 UserInfo 更新protected override void OnPropertyChanged(string propertyName = null){base.OnPropertyChanged(propertyName);if (propertyName == nameof(UserName) || propertyName == nameof(Age))RaisePropertyChanged(nameof(UserInfo));}
}
d. 高級用法

(1)批量通知多個屬性

通過 RaisePropertyChanged(null) 或指定空字符串,通知所有屬性更新(慎用,可能影響性能):

public void ResetAllProperties()
{_userName = "Default";_age = 0;RaisePropertyChanged(""); // 通知所有屬性更新
}

(2) 繼承與擴展

可繼承 ViewModelBase 并添加通用邏輯(如日志記錄、驗證):

public abstract class CustomViewModelBase : ViewModelBase
{protected void LogPropertyChange(string propertyName){Debug.WriteLine($"屬性 {propertyName} 已更新");}public override void RaisePropertyChanged(string propertyName = null){base.RaisePropertyChanged(propertyName);LogPropertyChange(propertyName);}
}


4. MvvmLight 中的命令對象

a. 命令對象的作用
  • 解耦 UI 與業務邏輯:將用戶操作(如點擊按鈕)映射到 ViewModel 的方法。
  • 控制可執行狀態:根據條件動態啟用或禁用 UI 元素(例如按鈕的 IsEnabled)。
  • 支持參數傳遞:允許從 UI 傳遞參數到 ViewModel(如選中項的 ID)。
b. 核心接口:ICommand

所有命令對象均實現 System.Windows.Input.ICommand 接口,其定義如下:

public interface ICommand
{event EventHandler CanExecuteChanged; // 通知命令可執行狀態變化bool CanExecute(object parameter);    // 判斷命令是否可執行void Execute(object parameter);       // 執行命令邏輯
}
c. MvvmLight 中的 RelayCommand

MvvmLight 提供 RelayCommandRelayCommand<T> 類,簡化了 ICommand 的實現。

(1) 基本用法(無參數)

public class MainViewModel : ViewModelBase
{public RelayCommand SaveCommand { get; }public MainViewModel(){// 初始化命令:綁定方法 + 可執行條件SaveCommand = new RelayCommand(SaveData, CanSave);}private void SaveData(){// 保存邏輯}private bool CanSave(){return !string.IsNullOrEmpty(Name); // 僅當 Name 非空時按鈕可用}
}

(2) 支持參數傳遞(RelayCommand<T>)

public RelayCommand<string> FilterCommand { get; }public MainViewModel()
{FilterCommand = new RelayCommand<string>(param => ApplyFilter(param), param => !string.IsNullOrEmpty(param));
}private void ApplyFilter(string keyword)
{// 根據關鍵字過濾數據
}
d. 動態更新命令的可執行狀態

(1) 手動觸發更新

CanExecute 依賴的屬性變化時,調用 RelayCommandRaiseCanExecuteChanged 方法:

private string _name;
public string Name
{get => _name;set{Set(ref _name, value);SaveCommand.RaiseCanExecuteChanged(); // 觸發重新檢查 CanSave}
}

(1) 自動觸發更新

利用 ViewModelBaseSet 方法自動觸發屬性變更通知,無需手動調用 RaiseCanExecuteChanged

private string _name;
public string Name
{get => _name;set => Set(ref _name, value); // Set 方法已自動觸發 PropertyChanged
}// CanSave 方法中依賴 Name 屬性
private bool CanSave() => !string.IsNullOrEmpty(Name);
e. 高級用法

(1) 異步命令

直接在命令中執行異步操作時,需注意線程安全(通過 DispatcherHelper):

public RelayCommand LoadDataCommand { get; }public MainViewModel()
{LoadDataCommand = new RelayCommand(async () => await LoadDataAsync());
}private async Task LoadDataAsync()
{try{IsLoading = true;var data = await _dataService.GetData();// 更新 UI(確保在 UI 線程)DispatcherHelper.CheckBeginInvokeOnUI(() => DataList = data);}finally{IsLoading = false;}
}

(2) 復合命令

將多個命令組合成一個邏輯操作:

public RelayCommand SubmitAllCommand { get; }public MainViewModel()
{SubmitAllCommand = new RelayCommand(() =>{SaveCommand.Execute(null);LogCommand.Execute(null);}, () => SaveCommand.CanExecute(null) && LogCommand.CanExecute(null));
}

(3) 命令的泛型約束

public RelayCommand<int> DeleteItemCommand { get; }public MainViewModel()
{DeleteItemCommand = new RelayCommand<int>(id => DeleteItem(id), id => id > 0);
}private void DeleteItem(int itemId)
{// 刪除指定 ID 的項
}

5. Messenger 對象使用

MVVM 模式 中,Messenger 是一個用于實現 松耦合通信 的核心組件,尤其在 MvvmLight 框架 中被廣泛使用。它允許不同組件(如 ViewModel、View、服務)之間通過消息進行通信,而無需直接引用彼此,從而降低依賴、提升代碼可維護性。

a. Messenger 的核心作用
  • 解耦組件通信:組件無需持有對方引用,通過消息訂閱/發布機制交互。
  • 跨層級傳遞數據:例如從子 ViewModel 通知父 ViewModel,或跨頁面傳遞狀態。
  • 支持復雜場景:如廣播通知、請求-響應模式、事件聚合等。
b. MvvmLight 中的 Messenger 實現

MvvmLight 的 Messenger 類是一個靜態單例(Messenger.Default),提供消息的注冊、發送和注銷功能。其核心方法如下:

方法

作用

Register<TMessage>(object recipient, Action<TMessage> action)

訂閱類型為 TMessage

的消息。recipient

為接收者標識(通常為 this

)。

Send<TMessage>(TMessage message)

發送一條 TMessage

類型的消息,所有訂閱者會收到通知。

Unregister(object recipient)

注銷某個接收者的所有消息訂閱,避免內存泄漏。

c. 基本使用場景

(1) 發送簡單通知消息

  • 場景:ViewModel A 完成數據加載后,通知 ViewModel B 刷新界面。

發送消息方

// 發送一個無參數通知
Messenger.Default.Send(new NotificationMessage("DataLoaded"));

接收消息方(ViewModel B)

public ViewModelB()
{// 注冊接收 NotificationMessage 類型的消息Messenger.Default.Register<NotificationMessage>(this, message =>{if (message.Notification == "DataLoaded"){RefreshData();}});
}

(2) 傳遞數據對象

  • 場景:用戶選擇某條數據后,跨頁面傳遞選中項。

定義消息類型

public class ItemSelectedMessage
{public int ItemId { get; set; }public ItemSelectedMessage(int id) => ItemId = id;
}

發送方:

// 用戶選擇某項后發送消息
Messenger.Default.Send(new ItemSelectedMessage(selectedItem.Id));

接收方:

Messenger.Default.Register<ItemSelectedMessage>(this, message =>
{LoadItemDetails(message.ItemId); // 根據 ItemId 加載詳情
});
d. 高級用法

(1) 消息令牌(Token)

  • 作用:區分相同消息類型的不同用途,避免消息沖突。

發送帶令牌的消息

// 發送消息時指定令牌
Messenger.Default.Send(new NotificationMessage("UpdateChart"), "ChartToken" // 令牌標識
);

接收指定令牌的消息

Messenger.Default.Register<NotificationMessage>(this, message => UpdateChartData(), "ChartToken" // 僅接收帶有此令牌的消息
);

(2) 泛型消息

  • 場景:傳遞強類型數據,避免類型轉換。

定義泛型消息

public class GenericMessage<T>
{public T Content { get; }public GenericMessage(T content) => Content = content;
}

發送泛型消息

var data = new List<User>();
Messenger.Default.Send(new GenericMessage<List<User>>(data));

接收泛型消息

Messenger.Default.Register<GenericMessage<List<User>>>(this, message =>
{UserList = message.Content; // 直接獲取 List<User>
});

(3) 雙向通信(請求-響應模式)

  • 場景:ViewModel A 請求數據,ViewModel B 響應返回結果。

發送請求消息

public class DataRequestMessage
{public Action<string> Callback { get; set; } // 定義回調委托
}// 發送請求,并注冊回調
Messenger.Default.Send(new DataRequestMessage 
{ Callback = response => HandleResponse(response) 
});

接收請求并響應

Messenger.Default.Register<DataRequestMessage>(this, message =>
{var data = FetchDataFromService(); // 獲取數據message.Callback?.Invoke(data);    // 執行回調
});

6. DispatcherHelper 對象使用

  • 作用: 在非 UI 線程更新 UI。
  • 初始化:
DispatcherHelper.Initialize(); // 在 App.xaml.cs 中調用
  • 使用:
Task.Run(() =>{// 后臺線程操作DispatcherHelper.CheckBeginInvokeOnUI(() =>{// 更新 UI 元素StatusText = "Processing...";});});

7. SimpleIoc 對象使用

SimpleIocMvvmLight 框架中提供的一個輕量級依賴注入(Dependency Injection, DI)容器,用于管理應用程序中各個組件(如 ViewModel、服務、數據源)的依賴關系。它通過 控制反轉(IoC)依賴注入 機制,幫助開發者實現代碼解耦、提高可測試性和可維護性。

a. SimpleIoc 的核心作用
  • 解耦組件依賴:將類的依賴關系從代碼中抽離,通過容器統一管理。
  • 單例生命周期管理:默認以單例模式提供實例,避免重復創建對象。
  • 簡化實例獲取:通過接口或類型直接獲取已注冊的實例。
  • 支持構造函數注入:自動解析構造函數參數,完成依賴注入。
b. 核心方法與屬性

以下是 SimpleIoc 的常用方法及其功能:

方法/屬性

作用

Register<TInterface, TClass>()

注冊接口 TInterface

和其實現類 TClass

Register<TClass>()

直接注冊類型 TClass

(無接口)。

GetInstance<T>()

獲取類型 T

的實例(已注冊的接口或類)。

ContainsCreated<T>()

檢查類型 T

的實例是否已被創建。

Reset()

重置容器,清空所有注冊和實例(用于測試或重新初始化)。

IsRegistered<T>()

檢查類型 T

是否已注冊。

c. 基本使用步驟

(1) 注冊服務與 ViewModel

在應用程序啟動時(如 ViewModelLocatorApp.xaml.cs 中),注冊所有依賴項:

public class ViewModelLocator
{public ViewModelLocator(){// 注冊服務(接口 + 實現類)SimpleIoc.Default.Register<IDataService, DataService>();// 注冊 ViewModel(無接口)SimpleIoc.Default.Register<MainViewModel>();}// 提供 ViewModel 實例的公共屬性public MainViewModel Main => SimpleIoc.Default.GetInstance<MainViewModel>();
}

(2) 獲取實例

通過 GetInstance<T> 方法獲取已注冊的實例:

// 獲取 ViewModel 實例
var mainVM = SimpleIoc.Default.GetInstance<MainViewModel>();// 獲取服務實例
var dataService = SimpleIoc.Default.GetInstance<IDataService>();

(3) 構造函數注入

當注冊的類(如 ViewModel)依賴其他服務時,SimpleIoc 會自動解析構造函數參數:

public class MainViewModel : ViewModelBase
{private readonly IDataService _dataService;// 構造函數依賴注入:自動傳入已注冊的 IDataService 實例public MainViewModel(IDataService dataService){_dataService = dataService;}
}
d. 高級用法

(1) 單例模式 vs. 瞬時模式

單例模式(默認):整個應用程序生命周期內只創建一個實例。

// 默認單例模式
SimpleIoc.Default.Register<IDataService, DataService>();

瞬時模式:每次調用 GetInstance 時創建新實例。

SimpleIoc.Default.Register<IDataService, DataService>(createInstanceImmediately: false);
var service = SimpleIoc.Default.GetInstance<IDataService>(); // 每次返回新實例

(2) 手動指定實例

允許直接注冊一個已存在的對象實例:

var logger = new FileLogger();
SimpleIoc.Default.Register<ILogger>(() => logger); // 注冊現有實例

(3) 依賴覆蓋

在測試中,可以替換實現類以注入 Mock 對象:

// 生產環境注冊真實服務
SimpleIoc.Default.Register<IDataService, DataService>();// 測試環境覆蓋為 Mock 服務
SimpleIoc.Default.Unregister<IDataService>();
SimpleIoc.Default.Register<IDataService, MockDataService>();
e. 與 ViewModelLocator 結合使用

ViewModelLocator 是 MvvmLight 中用于集中管理 ViewModel 的類,通常與 SimpleIoc 配合使用,通過 XAML 綁定 ViewModel。

(1) 定義 ViewModelLocator

public class ViewModelLocator
{public ViewModelLocator(){// 注冊服務和 ViewModelSimpleIoc.Default.Register<IDataService, DataService>();SimpleIoc.Default.Register<MainViewModel>();}// 暴露 ViewModel 屬性供 XAML 綁定public MainViewModel Main => SimpleIoc.Default.GetInstance<MainViewModel>();
}

(2) 在 XAML 中聲明資源

App.xaml 中合并 ViewModelLocator

<Application.Resources><ResourceDictionary><vm:ViewModelLocator x:Key="Locator" /></ResourceDictionary>
</Application.Resources>

(3) 在 View 中綁定 ViewModel

<Window DataContext="{Binding Main, Source={StaticResource Locator}}"><!-- UI 元素綁定到 MainViewModel 的屬性 -->
</Window>


本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/897201.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/897201.shtml
英文地址,請注明出處:http://en.pswp.cn/news/897201.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

【Linux】線程同步與互斥

線程同步與互斥 一.線程互斥1.互斥相關概念2.互斥鎖 Mutex3.互斥鎖接口4.互斥鎖實現原理5.互斥鎖封裝 二.線程同步1.同步相關概念2.條件變量 Condition Variable3.條件變量接口4.條件變量封裝5.信號量 Semaphore6.信號量接口7.信號量封裝8.生產者 - 消費者模型1.基于 Blocking …

URIError: URI malformed

&#x1f90d; 前端開發工程師、技術日更博主、已過CET6 &#x1f368; 阿珊和她的貓_CSDN博客專家、23年度博客之星前端領域TOP1 &#x1f560; 牛客高級專題作者、打造專欄《前端面試必備》 、《2024面試高頻手撕題》、《前端求職突破計劃》 &#x1f35a; 藍橋云課簽約作者、…

linux c++11 gcc4 環境編譯安裝googletest/gtest v1.10

c11對應googletest/gtest 經過測試&#xff0c;c11對應版本是googletest v1.10.x 編譯安裝 編譯環境 sudo apt-get update sudo apt-get install -y build-essential cmake下載或git clone代碼 git clone https://github.com/google/googletest.git cd googletest git che…

鴻蒙與DeepSeek深度整合:構建下一代智能操作系統生態

前些天發現了一個巨牛的人工智能學習網站&#xff0c;通俗易懂&#xff0c;風趣幽默&#xff0c;忍不住分享一下給大家。點擊跳轉到網站。 https://www.captainbed.cn/north 目錄 技術融合背景與價值鴻蒙分布式架構解析DeepSeek技術體系剖析核心整合架構設計智能調度系統實現…

極狐GitLab 17.9 正式發布,40+ DevSecOps 重點功能解讀【二】

GitLab 是一個全球知名的一體化 DevOps 平臺&#xff0c;很多人都通過私有化部署 GitLab 來進行源代碼托管。極狐GitLab 是 GitLab 在中國的發行版&#xff0c;專門為中國程序員服務。可以一鍵式部署極狐GitLab。 學習極狐GitLab 的相關資料&#xff1a; 極狐GitLab 官網極狐…

LeetCode - 28 找出字符串中第一個匹配項的下標

題目來源 28. 找出字符串中第一個匹配項的下標 - 力扣&#xff08;LeetCode&#xff09; 題目解析 暴力解法 本題如果采用暴力解法的話&#xff0c;可以定義兩個指針 i&#xff0c;j&#xff0c;其中 i 指針用于掃描 S&#xff08;haystack&#xff09;串&#xff0c;j 指針…

Spring Boot 異步編程

文章目錄 一、異步方法的使用1. 開啟異步支持2. 定義異步方法3. 調用異步方法踩坑記錄心得體會 二、線程池配置1. 自定義線程池2. 使用自定義線程池踩坑記錄心得體會 三、異步任務的監控與管理1. 日志記錄2. 異常處理3. 線程池監控踩坑記錄心得體會 在現代應用程序開發中&#…

0.大模型開發知識點需求綜述

文章目錄 一、機器學習與深度學習基礎二、自然語言處理&#xff08;NLP&#xff09;基礎三、大模型架構四、訓練優化技術五、數據處理與預處理六、分布式訓練與并行化策略七、微調方法與參數高效微調八、訓練框架、工具與自動化流程九、評估與部署十、前沿技術與未來趨勢 已更新…

docker目錄掛載與卷映射的區別

在 Docker 中&#xff0c;目錄掛載&#xff08;Bind Mount&#xff09;和卷映射&#xff08;Volume Mount&#xff09;的命令語法差異主要體現在路徑格式上&#xff0c;具體表現為是否以斜杠&#xff08;/&#xff09;開頭。以下是兩者的核心區別及使用場景的總結&#xff1a; …

[Java基礎-線程篇]7_線程設計模式與總結

摘要&#xff1a;懶漢單例模式怎么變得線程安全&#xff1f;Master-Worker歸并模式&#xff0c;工作竊取算法。Java線程相關源碼使用了什么設計模式&#xff1f; 資料引用&#xff1a;《Java高并發核心編程卷2》 目錄 線程安全的單例模式 Master-Worker模式 工作竊取算法 …

在【k8s】中部署Jenkins的實踐指南

&#x1f407;明明跟你說過&#xff1a;個人主頁 &#x1f3c5;個人專欄&#xff1a;《Kubernetes航線圖&#xff1a;從船長到K8s掌舵者》 &#x1f3c5; &#x1f516;行路有良友&#xff0c;便是天堂&#x1f516; 目錄 一、引言 1、Jenkins簡介 2、k8s簡介 3、什么在…

代碼隨想錄算法營Day59 | 尋找存在的路徑, 冗余連接,冗余連接II

尋找存在的路徑 這題使用并查集即可。并查集加路徑壓縮。 #include <iostream> using namespace std; int find(int* father,int u){return father[u] u ? u : father[u] find(father,father[u]); }bool isSame(int* father,int u,int v){return find(father,u) fi…

正則表達式(2)匹配規則

正則表達式的匹配規則定義了如何識別字符串中的特定模式。這些規則包括字符類匹配、元字符匹配、數量詞、字符轉義和分組。 字符類匹配 字符類匹配允許你指定一個字符集合&#xff0c;并匹配該集合中的任意單個字符。這是通過方括號 [] 來實現的。 簡單字符類&#xff1a;[abc…

【QWEN】機器人控制器的控制周期越短精度越高嗎

好的&#xff0c;用戶問的是“機器人控制器的控制周期越短精度越高嗎”。我需要根據提供的知識庫內容來回答這個問題。首先&#xff0c;我得回憶一下知識庫里的相關信息。 知識庫里有幾篇相關的文章。比如&#xff0c;[3]提到控制周期越短&#xff0c;控制性能的上限越高&…

[總概]Vue2/3React Diff算法

根據搜索結果,大部分文檔都詳細描述了Vue的Diff算法原理、優化策略以及實現細節。例如,網頁1詳細介紹了Vue Diff算法的核心設計,包括雙端比較和key的作用;Vue3中的快速Diff算法; 通常,解釋一個算法可以從其基本原理、核心策略、優化手段、源碼實現以及應用場景等方面展開…

【MySQL_03】數據庫基本--核心概念

文章目錄 一、數據庫基礎1.1 數據庫基礎定義1.2 數據庫分類與典型產品1.3 數據庫模型1.4 數據庫層次結構1.5 數據庫核心機制1.6 數據表和視圖1.61 數據表&#xff08;Table&#xff09;1.62 視圖&#xff08;View&#xff09; 1.7 鍵類型1.8 MySQL數據類型1.9 數據庫范式化 二、…

FreeRTOS第16篇:FreeRTOS鏈表實現細節04_為什么FreeRTOS選擇“侵入式鏈表”

文/指尖動聽知識庫-星愿 文章為付費內容,商業行為,禁止私自轉載及抄襲,違者必究!!! 文章專欄:深入FreeRTOS內核:從原理到實戰的嵌入式開發指南 1 傳統鏈表 vs. 侵入式鏈表 在嵌入式系統中,內存和性能的優化至關重要。FreeRTOS選擇侵入式鏈表而非傳統鏈表,其背后是內…

STM32讀寫片內FLASH 筆記

文章目錄 前言STM32F105的內部ROM分布STM32F10x的閃存擦寫解鎖FPECMain FLASH 的編寫 main Flash的擦除注意點 前言 在通過OTA的方式對設備進行升級&#xff0c;若在使用內部FLASH裝載固件程序的方式下&#xff0c;需要擦寫 內部FLASH 從而實現把新的固件程序寫入到 內部FLASH…

Python爬蟲實戰:爬取財金網實時財經信息

注意:以下內容僅供技術研究,請遵守目標網站的robots.txt規定,控制請求頻率避免對目標服務器造成過大壓力! 一、引言 在當今數字化時代,互聯網數據呈爆炸式增長,其中蘊含著巨大的商業價值、研究價值和社會價值。從金融市場動態分析到行業趨勢研究,從輿情監測到學術信息收…

3.3.2 用仿真圖實現點燈效果

文章目錄 文章介紹Keil生成.hex代碼Proteus仿真圖中導入.hex代碼文件開始仿真 文章介紹 點燈之前需要準備好仿真圖keil代碼 仿真圖參考前文&#xff1a;3.3.2 Proteus第一個仿真圖 keil安裝參考前文&#xff1a;3.1.2 Keil4安裝教程 keil新建第一個項目參考前文&#xff1a;3.1…