diff --git a/.gitignore b/.gitignore index daa0e6d..5827186 100644 --- a/.gitignore +++ b/.gitignore @@ -62,3 +62,23 @@ coverage *.sw? *.tsbuildinfo + +logs/ +[b|B]in +[o|O]bj +.vs +[E|e]xclude + +# Default ignored files +/shelf/ +/workspace.xml +# Rider ignored files +/contentModel.xml +/.idea.SQLTutorial.iml +/modules.xml +/projectSettingsUpdater.xml +# Editor-based HTTP Client requests +/httpRequests/ +# Datasource local storage ignored files +/dataSources/ +/dataSources.local.xml diff --git a/CSharp/SQLTutorial/ADO-1-Start/ADO-1-Start.csproj b/CSharp/SQLTutorial/ADO-1-Start/ADO-1-Start.csproj new file mode 100644 index 0000000..7611e3e --- /dev/null +++ b/CSharp/SQLTutorial/ADO-1-Start/ADO-1-Start.csproj @@ -0,0 +1,16 @@ + + + + Exe + net8.0 + ADO_1_Start + enable + enable + + + + + + + + diff --git a/CSharp/SQLTutorial/ADO-1-Start/Program.cs b/CSharp/SQLTutorial/ADO-1-Start/Program.cs new file mode 100644 index 0000000..cf65c97 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-1-Start/Program.cs @@ -0,0 +1,36 @@ +using MySqlConnector; + +namespace ADO_1_Start; + +public class Program +{ + private static readonly string Host = "rm-bp12z6hlv46vi6g8mro.mysql.rds.aliyuncs.com"; + private static readonly string Database = "bunny_test"; + private static readonly uint Port = 3306; + private static readonly string Username = "root"; + private static readonly string Password = "0212zkw!"; + + public static void Main(string[] args) + { + var mySqlConnectionStringBuilder = new MySqlConnectionStringBuilder + { + Server = Host, Port = Port, + Database = Database, + UserID = Username, Password = Password + }; + Console.WriteLine(mySqlConnectionStringBuilder.ConnectionString); + using (var mySqlConnection = new MySqlConnection(mySqlConnectionStringBuilder.ConnectionString)) + { + mySqlConnection.Open(); + + var mySqlCommand = new MySqlCommand("select * from sys_user"); + mySqlCommand.Connection = mySqlConnection; + + var mySqlDataReader = mySqlCommand.ExecuteReader(); + mySqlDataReader.Read(); + + for (var i = 0; i < mySqlDataReader.FieldCount; i++) + Console.Write(mySqlDataReader.GetName(i) + (i < mySqlDataReader.FieldCount - 1 ? "\t" : "\n")); + } + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-1-Connect/ADO-Web-1-Connect.csproj b/CSharp/SQLTutorial/ADO-Web-1-Connect/ADO-Web-1-Connect.csproj new file mode 100644 index 0000000..579a0c7 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-1-Connect/ADO-Web-1-Connect.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + WebApplication1 + + + + + + + + + diff --git a/CSharp/SQLTutorial/ADO-Web-1-Connect/ADO-Web-1-Connect.csproj.user b/CSharp/SQLTutorial/ADO-Web-1-Connect/ADO-Web-1-Connect.csproj.user new file mode 100644 index 0000000..9ff5820 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-1-Connect/ADO-Web-1-Connect.csproj.user @@ -0,0 +1,6 @@ + + + + https + + \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-1-Connect/Controller/HomeController.cs b/CSharp/SQLTutorial/ADO-Web-1-Connect/Controller/HomeController.cs new file mode 100644 index 0000000..f1203d8 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-1-Connect/Controller/HomeController.cs @@ -0,0 +1,15 @@ +using Microsoft.AspNetCore.Mvc; +using WebApplication1.Data; + +namespace WebApplication1.Controller; + +[Route("api/[controller]")] +public class HomeController +{ + [HttpGet] + public string? Index() + { + var configuration = AppCConfigurationServices.Configuration; + return configuration.GetConnectionString("BunnyTest"); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-1-Connect/Data/AppCConfigurationServices.cs b/CSharp/SQLTutorial/ADO-Web-1-Connect/Data/AppCConfigurationServices.cs new file mode 100644 index 0000000..4b0616e --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-1-Connect/Data/AppCConfigurationServices.cs @@ -0,0 +1,18 @@ +using Microsoft.Extensions.Configuration.Json; + +namespace WebApplication1.Data; + +public class AppCConfigurationServices +{ + static AppCConfigurationServices() + { + Configuration = new ConfigurationBuilder() + .Add(new JsonConfigurationSource + { + Path = "appsettings.json", + ReloadOnChange = true + }).Build(); + } + + public static IConfiguration Configuration { get; set; } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-1-Connect/Program.cs b/CSharp/SQLTutorial/ADO-Web-1-Connect/Program.cs new file mode 100644 index 0000000..8c66695 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-1-Connect/Program.cs @@ -0,0 +1,27 @@ +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddCors(options => +{ + options.AddDefaultPolicy(policyBuilder => policyBuilder.AllowAnyOrigin().AllowAnyMethod().AllowAnyHeader()); +}); + +// Add services to the container. +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); +builder.Services.AddControllers(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); +app.UseCors(); +app.UseAuthorization(); +app.MapControllers(); + +app.Run(); \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-1-Connect/Properties/launchSettings.json b/CSharp/SQLTutorial/ADO-Web-1-Connect/Properties/launchSettings.json new file mode 100644 index 0000000..8983b74 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-1-Connect/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:13883", + "sslPort": 44388 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5153", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7156;http://localhost:5153", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/CSharp/SQLTutorial/ADO-Web-1-Connect/WebApplication1.http b/CSharp/SQLTutorial/ADO-Web-1-Connect/WebApplication1.http new file mode 100644 index 0000000..9e31f7a --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-1-Connect/WebApplication1.http @@ -0,0 +1,6 @@ +@WebApplication1_HostAddress = http://localhost:5153 + +GET {{WebApplication1_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/CSharp/SQLTutorial/ADO-Web-1-Connect/appsettings.Development.json b/CSharp/SQLTutorial/ADO-Web-1-Connect/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-1-Connect/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/CSharp/SQLTutorial/ADO-Web-1-Connect/appsettings.json b/CSharp/SQLTutorial/ADO-Web-1-Connect/appsettings.json new file mode 100644 index 0000000..c3dd6b9 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-1-Connect/appsettings.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "ConnectionStrings": { + "BunnyTest": "Server=rm-bp12z6hlv46vi6g8mro.mysql.rds.aliyuncs.com;Port=3306;User ID=root;Password=0212zkw!;Database=bunny_test" + } +} diff --git a/CSharp/SQLTutorial/ADO-Web-2-Connect/ADO-Web-2-Connect.csproj b/CSharp/SQLTutorial/ADO-Web-2-Connect/ADO-Web-2-Connect.csproj new file mode 100644 index 0000000..1bf4aaf --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-2-Connect/ADO-Web-2-Connect.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + ADO_Web_2_Connect + + + + + + + + + diff --git a/CSharp/SQLTutorial/ADO-Web-2-Connect/ADO-Web-2-Connect.csproj.user b/CSharp/SQLTutorial/ADO-Web-2-Connect/ADO-Web-2-Connect.csproj.user new file mode 100644 index 0000000..9ff5820 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-2-Connect/ADO-Web-2-Connect.csproj.user @@ -0,0 +1,6 @@ + + + + https + + \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-2-Connect/Controller/HomeController.cs b/CSharp/SQLTutorial/ADO-Web-2-Connect/Controller/HomeController.cs new file mode 100644 index 0000000..905815a --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-2-Connect/Controller/HomeController.cs @@ -0,0 +1,76 @@ +using ADO_Web_2_Connect.Data; +using ADO_Web_2_Connect.Helper; +using ADO_Web_2_Connect.Model; +using Microsoft.AspNetCore.Mvc; + +namespace ADO_Web_2_Connect.Controller; + +[Route("/api/[controller]")] +public class HomeController : ControllerBase +{ + [HttpGet("Index")] + public IActionResult Index() + { + var connectionString = AppConfigurationServices.Configuration.GetConnectionString("BunnyTest"); + return new OkObjectResult(connectionString); + } + + [HttpGet] + public async Task>> GetAll() + { + const string sql = "SELECT * FROM news_type"; + var readerAsync = await MysqlHelper.ExecuteReaderAsync(sql); + + var newTypes = new List(); + if (!readerAsync.HasRows) return newTypes; + + while (readerAsync.Read()) + newTypes.Add(new NewType + { + Id = readerAsync.GetInt32(0), NewsTypeTitle = readerAsync.GetString(1), + IsEnabled = readerAsync.GetBoolean(2) + }); + + readerAsync.Close(); + return newTypes; + } + + [HttpGet("GetById/{id:int}")] + public async Task> GetById(int id) + { + var sql = $"SELECT * FROM news_type WHERE id={id}"; + var mySqlDataReader = await MysqlHelper.ExecuteReaderAsync(sql); + + // 是否存在数据 + if (!mySqlDataReader.HasRows) return new NotFoundResult(); + + var newType = new NewType(); + while (mySqlDataReader.Read()) + newType = new NewType + { + Id = mySqlDataReader.GetInt32(0), + NewsTypeTitle = mySqlDataReader.GetString(1), + IsEnabled = mySqlDataReader.GetBoolean(2) + }; + + mySqlDataReader.Close(); + return newType; + } + + [HttpPost] + public async Task Insert(NewType? newType) + { + if (newType == null) return 0; + + var sql = + $"INSERT INTO news_type ( `id`, `news_type_title`, `is_enable` ) VALUES ( {newType.Id}, '{newType.NewsTypeTitle}', {newType.IsEnabled} )"; + return await MysqlHelper.ExecuteQueryAsync(sql); + } + + [HttpDelete] + public async Task DeleteById(int id) + { + var sql = $"DELETE FROM news_type WHERE id={id}"; + return await MysqlHelper.ExecuteQueryAsync(sql); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-2-Connect/Data/AppConfigurationServices.cs b/CSharp/SQLTutorial/ADO-Web-2-Connect/Data/AppConfigurationServices.cs new file mode 100644 index 0000000..6e07175 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-2-Connect/Data/AppConfigurationServices.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.Configuration.Json; + +namespace ADO_Web_2_Connect.Data; + +public class AppConfigurationServices +{ + static AppConfigurationServices() + { + Configuration = new ConfigurationBuilder().Add(new JsonConfigurationSource + { + Path = "appsettings.json", + ReloadOnChange = true + }).Build(); + } + + public static IConfiguration Configuration { get; set; } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-2-Connect/Helper/MysqlHelper.cs b/CSharp/SQLTutorial/ADO-Web-2-Connect/Helper/MysqlHelper.cs new file mode 100644 index 0000000..918fa2b --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-2-Connect/Helper/MysqlHelper.cs @@ -0,0 +1,108 @@ +using System.Data; +using ADO_Web_2_Connect.Data; +using MySqlConnector; + +namespace ADO_Web_2_Connect.Helper; + +public class MysqlHelper +{ + private static readonly string? ConnStr; + + static MysqlHelper() + { + ConnStr ??= AppConfigurationServices.Configuration.GetConnectionString("BunnyTest"); + } + + /// + /// 查询数据库 + /// + /// SQL语句 + /// + public static int ExecuteNonQuery(string sql) + { + using var mySqlConnection = new MySqlConnection(ConnStr); + mySqlConnection.Open(); + var command = new MySqlCommand(sql, mySqlConnection); + return command.ExecuteNonQuery(); + } + + /// + /// 异步查询数据库 + /// + /// SQL语句 + /// + public static async Task ExecuteQueryAsync(string sql) + { + await using var mySqlConnection = new MySqlConnection(ConnStr); + mySqlConnection.Open(); + var command = new MySqlCommand(sql, mySqlConnection); + return await command.ExecuteNonQueryAsync(); + } + + /// + /// 读取数据库流 + /// + /// SQL语句 + /// + public static MySqlDataReader ExecuteReader(string sql) + { + using var mySqlConnection = new MySqlConnection(ConnStr); + mySqlConnection.Open(); + var command = new MySqlCommand(sql, mySqlConnection); + return command.ExecuteReader(CommandBehavior.CloseConnection); + } + + /// + /// 异步读取数据库流 + /// + /// SQL语句 + /// + public static async Task ExecuteReaderAsync(string sql) + { + var mySqlConnection = new MySqlConnection(ConnStr); + mySqlConnection.Open(); + var command = new MySqlCommand(sql, mySqlConnection); + return await command.ExecuteReaderAsync(); + } + + /// + /// 异步读取数据库流 + /// + /// SQL语句 + /// + public static async Task ExecuteReaderAsyncTest(string sql) + { + await using var mySqlConnection = new MySqlConnection(); + mySqlConnection.Open(); + var command = new MySqlCommand(sql, mySqlConnection); + return await command.ExecuteReaderAsync(CommandBehavior.CloseConnection); + } + + /// + /// 获取首行首列的值 + /// + /// SQL语句 + /// + public static object? ExecuteScalar(string sql) + { + using var mySqlConnection = new MySqlConnection(ConnStr); + mySqlConnection.Open(); + var mySqlCommand = mySqlConnection.CreateCommand(); + mySqlCommand.CommandText = sql; + mySqlCommand.CommandType = CommandType.Text; + return mySqlCommand.ExecuteScalar(); + } + + /// + /// 异步获取首行首列 + /// + /// SQL语句 + /// + public static async Task ExecuteScalarAsync(string sql) + { + await using var mySqlConnection = new MySqlConnection(ConnStr); + mySqlConnection.Open(); + var mySqlCommand = new MySqlCommand(sql, mySqlConnection); + return await mySqlCommand.ExecuteScalarAsync(); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-2-Connect/Model/NewType.cs b/CSharp/SQLTutorial/ADO-Web-2-Connect/Model/NewType.cs new file mode 100644 index 0000000..94cea10 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-2-Connect/Model/NewType.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace ADO_Web_2_Connect.Model; + +public class NewType +{ + /// + /// 新闻分类Id + /// + [Column("id")] + public int Id { get; set; } + + /// + /// 新闻分类标题 + /// + [Column("news_type_title")] + public string? NewsTypeTitle { get; set; } + + /// + /// 是否启用 + /// + [Column("is_enable")] + public bool? IsEnabled { get; set; } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-2-Connect/Program.cs b/CSharp/SQLTutorial/ADO-Web-2-Connect/Program.cs new file mode 100644 index 0000000..2d070ff --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-2-Connect/Program.cs @@ -0,0 +1,28 @@ +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddCors(options => +{ + options.AddDefaultPolicy(policyBuilder => policyBuilder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin()); +}); + +// Add services to the container. +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); +builder.Services.AddControllers(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); +app.UseCors(); +app.UseAuthorization(); +app.MapControllers(); + +app.Run(); \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-2-Connect/Properties/launchSettings.json b/CSharp/SQLTutorial/ADO-Web-2-Connect/Properties/launchSettings.json new file mode 100644 index 0000000..d317f8d --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-2-Connect/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:17876", + "sslPort": 44385 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5042", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7259;http://localhost:5042", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/CSharp/SQLTutorial/ADO-Web-2-Connect/appsettings.Development.json b/CSharp/SQLTutorial/ADO-Web-2-Connect/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-2-Connect/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/CSharp/SQLTutorial/ADO-Web-2-Connect/appsettings.json b/CSharp/SQLTutorial/ADO-Web-2-Connect/appsettings.json new file mode 100644 index 0000000..8d9ca8c --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-2-Connect/appsettings.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "ConnectionStrings": { + "BunnyTest": "Server=rm-bp12z6hlv46vi6g8mro.mysql.rds.aliyuncs.com;Port=3306;User ID=root;Password=0212zkw!;Database=news" + } +} diff --git a/CSharp/SQLTutorial/ADO-Web-3-Connect/ADO-Web-3-Connect.csproj b/CSharp/SQLTutorial/ADO-Web-3-Connect/ADO-Web-3-Connect.csproj new file mode 100644 index 0000000..6f58e21 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-3-Connect/ADO-Web-3-Connect.csproj @@ -0,0 +1,16 @@ + + + + net8.0 + enable + enable + ADO_Web_3_Connect + + + + + + + + + diff --git a/CSharp/SQLTutorial/ADO-Web-3-Connect/ADO-Web-3-Connect.csproj.user b/CSharp/SQLTutorial/ADO-Web-3-Connect/ADO-Web-3-Connect.csproj.user new file mode 100644 index 0000000..9ff5820 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-3-Connect/ADO-Web-3-Connect.csproj.user @@ -0,0 +1,6 @@ + + + + https + + \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-3-Connect/Controller/NewsController.cs b/CSharp/SQLTutorial/ADO-Web-3-Connect/Controller/NewsController.cs new file mode 100644 index 0000000..cb25a2e --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-3-Connect/Controller/NewsController.cs @@ -0,0 +1,91 @@ +using ADO_Web_3_Connect.Helper; +using ADO_Web_3_Connect.Model; +using Microsoft.AspNetCore.Mvc; + +namespace ADO_Web_3_Connect.Controller; + +[Route("api/[controller]")] +public class NewsController : ControllerBase +{ + [HttpGet] + public async Task> GetNews() + { + const string sql = "select * from news"; + var mySqlDataReader = await MysqlHelper.ExecuteReaderAsync(sql); + var news = new List(); + + while (mySqlDataReader.Read()) + news.Add(new News + { + Id = mySqlDataReader.GetInt32(0), + Title = mySqlDataReader.GetString(1), + Content = mySqlDataReader.GetString(2), + NewsTypeId = mySqlDataReader.GetInt32(3) + }); + return news; + } + + [HttpGet("{id:int}")] + public async Task GetNewsById(int id) + { + var sql = + $"SELECT n.id, n.news_title, n.content, n.new_type AS news_type_id, nt.news_type_title FROM news n LEFT JOIN news_type nt ON nt.id = n.new_type WHERE n.id = {id}"; + var readerAsync = await MysqlHelper.ExecuteReaderAsync(sql); + + var news = new News(); + while (readerAsync.Read()) + news = new News + { + Id = readerAsync.GetInt32(0), + Title = readerAsync.GetString(1), + Content = readerAsync.GetString(2), + NewsTypeId = readerAsync.GetInt32(3), + NewsTypeTitle = readerAsync.GetString(4) + }; + + readerAsync.Close(); + return news; + } + + [HttpGet("Query")] + public async Task> Query(string keyword) + { + var sql = + $"SELECT n.id, n.news_title, n.content, n.new_type AS news_type_id, nt.news_type_title FROM news n LEFT JOIN news_type nt ON nt.id = n.new_type WHERE n.content LIKE '%{keyword}%' OR n.news_title LIKE '%{keyword}%'"; + var mySqlDataReader = await MysqlHelper.ExecuteReaderAsync(sql); + + var list = new List(); + while (mySqlDataReader.Read()) + { + var news = new News + { + Id = mySqlDataReader.GetInt32(0), + Title = mySqlDataReader.GetString(1), + Content = mySqlDataReader.GetString(2), + NewsTypeId = mySqlDataReader.GetInt32(3), + NewsTypeTitle = mySqlDataReader.GetString(4) + }; + list.Add(news); + } + + mySqlDataReader.Close(); + return list; + } + + [HttpPost] + public async Task Create(News? news) + { + if (news == null) return 0; + + var sql = + $"insert into news (id, news_title, content, new_type) values ({news.Id},'{news.Title}','{news.Content}',{news.NewsTypeId})"; + return await MysqlHelper.ExecuteNoeQueryAsync(sql); + } + + [HttpDelete("{id:int}")] + public async Task> Delete(int id) + { + var executeNoeQueryAsync = await MysqlHelper.ExecuteNoeQueryAsync($"delete from news where id={id}"); + return executeNoeQueryAsync; + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-3-Connect/Controller/NewsTypeController.cs b/CSharp/SQLTutorial/ADO-Web-3-Connect/Controller/NewsTypeController.cs new file mode 100644 index 0000000..9d9bee3 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-3-Connect/Controller/NewsTypeController.cs @@ -0,0 +1,76 @@ +using ADO_Web_3_Connect.Data; +using ADO_Web_3_Connect.Helper; +using ADO_Web_3_Connect.Model; +using Microsoft.AspNetCore.Mvc; + +namespace ADO_Web_3_Connect.Controller; + +[Route("/api/[controller]")] +public class NewsTypeController : ControllerBase +{ + [HttpGet("Index")] + public IActionResult Index() + { + var connectionString = AppConfigurationServices.Configuration.GetConnectionString("BunnyTest"); + return new OkObjectResult(connectionString); + } + + [HttpGet] + public async Task>> GetAll() + { + const string sql = "SELECT * FROM news_type"; + var readerAsync = await MysqlHelper.ExecuteReaderAsync(sql); + + var newTypes = new List(); + if (!readerAsync.HasRows) return newTypes; + + while (readerAsync.Read()) + newTypes.Add(new NewType + { + Id = readerAsync.GetInt32(0), NewsTypeTitle = readerAsync.GetString(1), + IsEnabled = readerAsync.GetBoolean(2) + }); + + readerAsync.Close(); + return newTypes; + } + + [HttpGet("GetById/{id:int}")] + public async Task> GetById(int id) + { + var sql = $"SELECT * FROM news_type WHERE id={id}"; + var mySqlDataReader = await MysqlHelper.ExecuteReaderAsync(sql); + + // 是否存在数据 + if (!mySqlDataReader.HasRows) return new NotFoundResult(); + + var newType = new NewType(); + while (mySqlDataReader.Read()) + newType = new NewType + { + Id = mySqlDataReader.GetInt32(0), + NewsTypeTitle = mySqlDataReader.GetString(1), + IsEnabled = mySqlDataReader.GetBoolean(2) + }; + + mySqlDataReader.Close(); + return newType; + } + + [HttpPost] + public async Task Insert(NewType? newType) + { + if (newType == null) return 0; + + var sql = + $"INSERT INTO news_type ( `id`, `news_type_title`, `is_enable` ) VALUES ( {newType.Id}, '{newType.NewsTypeTitle}', {newType.IsEnabled} )"; + return await MysqlHelper.ExecuteNoeQueryAsync(sql); + } + + [HttpDelete] + public async Task DeleteById(int id) + { + var sql = $"DELETE FROM news_type WHERE id={id}"; + return await MysqlHelper.ExecuteNoeQueryAsync(sql); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-3-Connect/Data/AppConfigurationServices.cs b/CSharp/SQLTutorial/ADO-Web-3-Connect/Data/AppConfigurationServices.cs new file mode 100644 index 0000000..9ded28b --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-3-Connect/Data/AppConfigurationServices.cs @@ -0,0 +1,17 @@ +using Microsoft.Extensions.Configuration.Json; + +namespace ADO_Web_3_Connect.Data; + +public class AppConfigurationServices +{ + public static IConfiguration Configuration; + + static AppConfigurationServices() + { + Configuration = new ConfigurationBuilder().Add(new JsonConfigurationSource + { + Path = "appsettings.json", + ReloadOnChange = true + }).Build(); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-3-Connect/Helper/MysqlHelper.cs b/CSharp/SQLTutorial/ADO-Web-3-Connect/Helper/MysqlHelper.cs new file mode 100644 index 0000000..374324f --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-3-Connect/Helper/MysqlHelper.cs @@ -0,0 +1,93 @@ +using System.Data; +using ADO_Web_3_Connect.Data; +using MySqlConnector; + +namespace ADO_Web_3_Connect.Helper; + +public class MysqlHelper +{ + private static readonly string? ConnStr; + + static MysqlHelper() + { + ConnStr ??= AppConfigurationServices.Configuration.GetConnectionString("BunnyTest"); + } + + /// + /// 查询数据库 + /// + /// SQL语句 + /// + public static int ExecuteNonQuery(string sql) + { + using var mySqlConnection = new MySqlConnection(ConnStr); + mySqlConnection.Open(); + var mySqlCommand = new MySqlCommand(sql, mySqlConnection); + return mySqlCommand.ExecuteNonQuery(); + } + + /// + /// 异步查询数据库 + /// + /// SQL语句 + /// + public static async Task ExecuteNoeQueryAsync(string sql) + { + var mySqlConnection = new MySqlConnection(ConnStr); + mySqlConnection.Open(); + var mySqlCommand = new MySqlCommand(sql, mySqlConnection); + return await mySqlCommand.ExecuteNonQueryAsync(); + } + + /// + /// 读取数据库流 + /// + /// SQL语句 + /// + public static MySqlDataReader ExecuteReader(string sql) + { + var mySqlConnection = new MySqlConnection(ConnStr); + mySqlConnection.Open(); + var mySqlCommand = new MySqlCommand(sql, mySqlConnection); + return mySqlCommand.ExecuteReader(CommandBehavior.CloseConnection); + } + + /// + /// 异步读取数据库流 + /// + /// SQL语句 + /// + public static async Task ExecuteReaderAsync(string sql) + { + var mySqlConnection = new MySqlConnection(ConnStr); + mySqlConnection.Open(); + var mySqlCommand = new MySqlCommand(sql, mySqlConnection); + return await mySqlCommand.ExecuteReaderAsync(); + } + + /// + /// 获取首行首列的值 + /// + /// SQL语句 + /// + public static object? ExecuteScalar(string sql) + { + using var mySqlConnection = new MySqlConnection(ConnStr); + mySqlConnection.Open(); + var mySqlCommand = new MySqlCommand(sql, mySqlConnection); + return mySqlCommand.ExecuteScalar(); + } + + /// + /// 异步获取首行首列 + /// + /// SQL语句 + /// + public static async Task ExecuteScalarAsync(string sql) + { + await using var mySqlConnection = new MySqlConnection(ConnStr); + mySqlConnection.Open(); + var mySqlCommand = new MySqlCommand(sql, mySqlConnection); + return await mySqlCommand.ExecuteScalarAsync(); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-3-Connect/Model/NewType.cs b/CSharp/SQLTutorial/ADO-Web-3-Connect/Model/NewType.cs new file mode 100644 index 0000000..b9f42ff --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-3-Connect/Model/NewType.cs @@ -0,0 +1,24 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace ADO_Web_3_Connect.Model; + +public class NewType +{ + /// + /// 新闻分类Id + /// + [Column("id")] + public int Id { get; set; } + + /// + /// 新闻分类标题 + /// + [Column("news_type_title")] + public string? NewsTypeTitle { get; set; } + + /// + /// 是否启用 + /// + [Column("is_enable")] + public bool? IsEnabled { get; set; } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-3-Connect/Model/News.cs b/CSharp/SQLTutorial/ADO-Web-3-Connect/Model/News.cs new file mode 100644 index 0000000..5cf08ea --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-3-Connect/Model/News.cs @@ -0,0 +1,32 @@ +using System.ComponentModel.DataAnnotations.Schema; + +namespace ADO_Web_3_Connect.Model; + +public class News +{ + /// + /// 主键 + /// + [Column("id")] + public int Id { get; set; } + + /// + /// 新闻标题 + /// + [Column("news_title")] + public string? Title { get; set; } + + /// + /// 新闻内容 + /// + [Column("news_content")] + public string? Content { get; set; } + + /// + /// 新闻类型id + /// + [Column("news_type")] + public int? NewsTypeId { get; set; } + + [NotMapped] public string? NewsTypeTitle { get; set; } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-3-Connect/Program.cs b/CSharp/SQLTutorial/ADO-Web-3-Connect/Program.cs new file mode 100644 index 0000000..60e9603 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-3-Connect/Program.cs @@ -0,0 +1,30 @@ +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddCors(options => +{ + options.AddDefaultPolicy(policyBuilder => + { + policyBuilder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin(); + }); +}); + +// Add services to the container. +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); +builder.Services.AddControllers(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); +app.UseCors(); +app.UseAuthorization(); +app.MapControllers(); +app.Run(); \ No newline at end of file diff --git a/CSharp/SQLTutorial/ADO-Web-3-Connect/Properties/launchSettings.json b/CSharp/SQLTutorial/ADO-Web-3-Connect/Properties/launchSettings.json new file mode 100644 index 0000000..5321783 --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-3-Connect/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:50314", + "sslPort": 44336 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5071", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7259;http://localhost:5071", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/CSharp/SQLTutorial/ADO-Web-3-Connect/appsettings.Development.json b/CSharp/SQLTutorial/ADO-Web-3-Connect/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-3-Connect/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/CSharp/SQLTutorial/ADO-Web-3-Connect/appsettings.json b/CSharp/SQLTutorial/ADO-Web-3-Connect/appsettings.json new file mode 100644 index 0000000..8d9ca8c --- /dev/null +++ b/CSharp/SQLTutorial/ADO-Web-3-Connect/appsettings.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "ConnectionStrings": { + "BunnyTest": "Server=rm-bp12z6hlv46vi6g8mro.mysql.rds.aliyuncs.com;Port=3306;User ID=root;Password=0212zkw!;Database=news" + } +} diff --git a/CSharp/SQLTutorial/Cors-1-Start/Cors-1-Start.csproj b/CSharp/SQLTutorial/Cors-1-Start/Cors-1-Start.csproj new file mode 100644 index 0000000..0a89608 --- /dev/null +++ b/CSharp/SQLTutorial/Cors-1-Start/Cors-1-Start.csproj @@ -0,0 +1,15 @@ + + + + net8.0 + enable + enable + Cors_1_Start + + + + + + + + diff --git a/CSharp/SQLTutorial/Cors-1-Start/Program.cs b/CSharp/SQLTutorial/Cors-1-Start/Program.cs new file mode 100644 index 0000000..b6734fd --- /dev/null +++ b/CSharp/SQLTutorial/Cors-1-Start/Program.cs @@ -0,0 +1,33 @@ +var builder = WebApplication.CreateBuilder(args); + +builder.Services.AddCors(options => +{ + options.AddPolicy("Cors示例", + policyBuilder => { policyBuilder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin(); }); +}); + +builder.Services.AddControllers(); +// Add services to the container. +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +app.UseCors("Cors示例"); + +app.UseAuthorization(); + +app.MapControllers(); + + +app.Run(); \ No newline at end of file diff --git a/CSharp/SQLTutorial/Cors-1-Start/Properties/launchSettings.json b/CSharp/SQLTutorial/Cors-1-Start/Properties/launchSettings.json new file mode 100644 index 0000000..7b4bfbf --- /dev/null +++ b/CSharp/SQLTutorial/Cors-1-Start/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:34628", + "sslPort": 44317 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5256", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7252;http://localhost:5256", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/CSharp/SQLTutorial/Cors-1-Start/appsettings.Development.json b/CSharp/SQLTutorial/Cors-1-Start/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/CSharp/SQLTutorial/Cors-1-Start/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/CSharp/SQLTutorial/Cors-1-Start/appsettings.json b/CSharp/SQLTutorial/Cors-1-Start/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/CSharp/SQLTutorial/Cors-1-Start/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Context/EFCoreContext.cs b/CSharp/SQLTutorial/EFCore-1-Start/Context/EFCoreContext.cs new file mode 100644 index 0000000..7d78cfb --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Context/EFCoreContext.cs @@ -0,0 +1,28 @@ +using EFCore_1_Start.Model; +using Microsoft.EntityFrameworkCore; + +namespace EFCore_1_Start.Context; + +/// +/// EFCore上下文对象 +/// +public class EfCoreContext : DbContext +{ + /// + /// EFCore上下文对象 + /// + /// DbContextOptions + public EfCoreContext(DbContextOptions options) : base(options) + { + } + + /// + /// 产品分类信息 + /// + public DbSet PCategories { get; set; } + + /// + /// 产品信息 + /// + public DbSet Products { get; set; } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Controller/PCategoryController.cs b/CSharp/SQLTutorial/EFCore-1-Start/Controller/PCategoryController.cs new file mode 100644 index 0000000..b7d4c7b --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Controller/PCategoryController.cs @@ -0,0 +1,72 @@ +using EFCore_1_Start.Model; +using EFCore_1_Start.Service.IServices; +using Microsoft.AspNetCore.Mvc; + +namespace EFCore_1_Start.Controller; + +/// +/// PCategory控制器 +/// +[Route("api/[controller]")] +public class PCategoryController : ControllerBase +{ + private readonly IPCategoryService _ipCategoryService; + + /// + /// PCategory服务 + /// + /// IPCategoryService + public PCategoryController(IPCategoryService ipCategoryService) + { + _ipCategoryService = ipCategoryService; + } + + /// + /// 获取所有产品信息 + /// + /// + [HttpGet] + public ActionResult> GetAll() + { + return _ipCategoryService.GetAll(); + } + + /// + /// 根据id查询产品 + /// + /// + /// + [HttpGet("{id:guid}")] + public ActionResult GetById(Guid id) + { + var pCategory = _ipCategoryService.GetById(id); + return pCategory; + } + + /// + /// 创建产品分类 + /// + /// + /// + [HttpPost] + public async Task CreatePCategory(PCategory? pCategory) + { + if (pCategory == null) return 0; + + pCategory.CId = Guid.NewGuid(); + return await _ipCategoryService.CreatePCategory(pCategory); + } + + /// + /// 根据Id删除 + /// + /// 主键 + /// + [HttpDelete("{id:guid}")] + public async Task DeletePCategoryById(Guid? id) + { + if (id == null) return 0; + + return await _ipCategoryService.DeletePCategoryById(id); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Controller/ProductController.cs b/CSharp/SQLTutorial/EFCore-1-Start/Controller/ProductController.cs new file mode 100644 index 0000000..d912c9a --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Controller/ProductController.cs @@ -0,0 +1,81 @@ +using EFCore_1_Start.Model; +using EFCore_1_Start.Service.IServices; +using Microsoft.AspNetCore.Mvc; + +namespace EFCore_1_Start.Controller; + +/// +/// 产品控制器 +/// +[Route("api/[controller]")] +public class ProductController : ControllerBase +{ + private readonly IProductService _productService; + + /// + /// ProductController + /// + /// IProductService + public ProductController(IProductService productService) + { + _productService = productService; + } + + /// + /// 根据id查询产品 + /// + /// Id + /// ActionResult - Product + [HttpGet("QueryListById/{id:guid}")] + public async Task>> QueryListById(Guid id) + { + return await _productService.QueryListById(id); + } + + /// + /// 根据分类Id查询产品信息 + /// + /// 分类Id + /// + /// Product + [HttpGet("QueryByKeyword")] + public async Task>> QueryByKeyword(Guid cId, string keyword) + { + return await _productService.QueryByKeyword(cId, keyword); + } + + /// + /// 根据id查询产品 + /// + /// Id + /// Product + [HttpGet("{id:guid}")] + public async Task> GetById(Guid id) + { + return await _productService.GetById(id); + } + + /// + /// 创建产品 + /// + /// 产品 + /// + [HttpPost] + public async Task> CreateProduct(Product? product) + { + if (product == null) return 0; + + return await _productService.CreateProduct(product); + } + + /// + /// 根据Id删除产品 + /// + /// Id + /// Task + [HttpDelete("{id:guid}")] + public async Task DeleteProduct(Guid id) + { + return await _productService.DeleteProduct(id); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/EFCore-1-Start.csproj b/CSharp/SQLTutorial/EFCore-1-Start/EFCore-1-Start.csproj new file mode 100644 index 0000000..7f0088b --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/EFCore-1-Start.csproj @@ -0,0 +1,21 @@ + + + + net8.0 + enable + enable + EFCore_1_Start + true + + + + + + all + runtime; build; native; contentfiles; analyzers; buildtransitive + + + + + + diff --git a/CSharp/SQLTutorial/EFCore-1-Start/EFCore-1-Start.csproj.user b/CSharp/SQLTutorial/EFCore-1-Start/EFCore-1-Start.csproj.user new file mode 100644 index 0000000..9ff5820 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/EFCore-1-Start.csproj.user @@ -0,0 +1,6 @@ + + + + https + + \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Model/PCategory.cs b/CSharp/SQLTutorial/EFCore-1-Start/Model/PCategory.cs new file mode 100644 index 0000000..04cf21a --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Model/PCategory.cs @@ -0,0 +1,23 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace EFCore_1_Start.Model; + +/// +/// 产品分类 +/// +[Table("p_category")] +public class PCategory +{ + /// + /// 主键 + /// + [Key] + public Guid? CId { get; set; } = Guid.NewGuid(); + + /// + /// 分类标题 + /// + [MaxLength(100)] + public string? CTitle { get; set; } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Model/Product.cs b/CSharp/SQLTutorial/EFCore-1-Start/Model/Product.cs new file mode 100644 index 0000000..5f55b9d --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Model/Product.cs @@ -0,0 +1,45 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace EFCore_1_Start.Model; + +/// +/// 产品 +/// +[Table("product")] +public class Product +{ + /// + /// 产品Id + /// + [Key] + public Guid? PId { get; set; } = Guid.NewGuid(); + + /// + /// 产品名称 + /// + [MaxLength(200)] + public string? PTitle { get; set; } + + /// + /// 产品数量 + /// + public int PSum { get; set; } + + /// + /// 产品价格 + /// + [Column(TypeName = "decimal(18,2)")] + public decimal PPrice { get; set; } + + /// + /// 产品分类Id + /// + public Guid PCategoryId { get; set; } + + /// + /// 产品分类信息 + /// + [ForeignKey("PCategoryId")] + public virtual PCategory? PCategory { get; set; } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Program.cs b/CSharp/SQLTutorial/EFCore-1-Start/Program.cs new file mode 100644 index 0000000..d2125cb --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Program.cs @@ -0,0 +1,78 @@ +using System.Diagnostics; +using System.Reflection; +using EFCore_1_Start.Context; +using EFCore_1_Start.Repositories; +using EFCore_1_Start.Repositories.IRepository; +using EFCore_1_Start.Service; +using EFCore_1_Start.Service.IServices; +using Microsoft.EntityFrameworkCore; +using Microsoft.OpenApi.Models; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddCors(options => +{ + options.AddDefaultPolicy(policyBuilder => + { + policyBuilder.AllowAnyHeader() + .AllowAnyMethod() + .AllowAnyOrigin(); + }); +}); + +// 注册 DbContext 服务 +builder.Services.AddDbContext(options => +{ + var connectionString = builder.Configuration.GetConnectionString("BunnyTest") ?? string.Empty; + options.UseMySql(connectionString, ServerVersion.AutoDetect(connectionString)); +}); + +// 添加控制器 +builder.Services.AddControllers(); + +// Add services to the container. +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(c => +{ + c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); + // ⭐ 添加 XML 注释支持 + var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); + c.IncludeXmlComments(xmlPath); +}); + +// 注入依赖 +builder.Services.AddTransient(); +builder.Services.AddScoped(); +builder.Services.AddTransient(); +builder.Services.AddScoped(); + +var app = builder.Build(); + +// 初始化数据库(Code First) +using (var scope = app.Services.CreateScope()) +{ + var dbContext = scope.ServiceProvider.GetRequiredService(); + + // 1. ⚠️ 注意:EnsureDeleted() 会 永久删除整个数据库,仅适用于开发和测试环境! + // var ensureDeleted = dbContext.Database.EnsureDeleted(); + // Console.WriteLine(ensureDeleted ? "Database created successfully!" : "Database already exists."); + + // 2. 如果数据库不存在,则创建(仅用于开发环境) + var dbCreated = dbContext.Database.EnsureCreatedAsync(); + Debug.WriteLine(await dbCreated ? "Database created successfully!" : "Database already exists."); +} + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.MapSwagger(); + app.UseSwaggerUI(); +} + +// app.UseHttpsRedirection(); +app.UseCors(); +app.UseAuthorization(); +app.MapControllers(); +app.Run(); \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Properties/launchSettings.json b/CSharp/SQLTutorial/EFCore-1-Start/Properties/launchSettings.json new file mode 100644 index 0000000..76c4c71 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:32321", + "sslPort": 44378 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5125", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7224;http://localhost:5125", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Repositories/IRepository/IPCategoryRepository.cs b/CSharp/SQLTutorial/EFCore-1-Start/Repositories/IRepository/IPCategoryRepository.cs new file mode 100644 index 0000000..24f3050 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Repositories/IRepository/IPCategoryRepository.cs @@ -0,0 +1,36 @@ +using EFCore_1_Start.Model; + +namespace EFCore_1_Start.Repositories.IRepository; + +/// +/// 产品分类数据库 +/// +public interface IPCategoryRepository +{ + /// + /// 创建产品分类 + /// + /// + /// + Task CreatePCategory(PCategory? pCategory); + + /// + /// 获取所有产品信息 + /// + /// + List GetAll(); + + /// + /// 根据id查找分类 + /// + /// Id + /// + PCategory? GetById(Guid id); + + /// + /// 根据Id删除 + /// + /// 主键 + /// + Task DeletePCategoryById(Guid? id); +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Repositories/IRepository/IProductRepository.cs b/CSharp/SQLTutorial/EFCore-1-Start/Repositories/IRepository/IProductRepository.cs new file mode 100644 index 0000000..373c238 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Repositories/IRepository/IProductRepository.cs @@ -0,0 +1,45 @@ +using EFCore_1_Start.Model; + +namespace EFCore_1_Start.Repositories.IRepository; + +/// +/// 产品数据库查询 +/// +public interface IProductRepository +{ + /// + /// 创建产品 + /// + /// 产品表单 + /// Task + Task Create(Product product); + + /// + /// 根据id查询产品 + /// + /// Id + /// ActionResult - Product + Task> QueryListById(Guid id); + + /// + /// 根据id查询产品 + /// + /// Id + /// Product + Task GetById(Guid id); + + /// + /// 根据Id删除产品 + /// + /// Id + /// Task + Task DeleteProduct(Guid id); + + /// + /// 根据分类Id查询产品信息 + /// + /// 分类Id + /// + /// Product + Task> QueryByKeyword(Guid cId, string keyword); +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Repositories/PCategoryRepository.cs b/CSharp/SQLTutorial/EFCore-1-Start/Repositories/PCategoryRepository.cs new file mode 100644 index 0000000..c01a6a7 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Repositories/PCategoryRepository.cs @@ -0,0 +1,56 @@ +using EFCore_1_Start.Context; +using EFCore_1_Start.Model; +using EFCore_1_Start.Repositories.IRepository; + +namespace EFCore_1_Start.Repositories; + +/// +/// 产品分类数据库查询实现 +/// +/// EfCoreContext +public class PCategoryRepository(EfCoreContext context) : IPCategoryRepository +{ + /// + /// 创建产品分类 + /// + /// + /// + public Task CreatePCategory(PCategory? pCategory) + { + if (pCategory == null) return Task.FromResult(0); + context.PCategories.Add(pCategory); + var saveChangesAsync = context.SaveChangesAsync(); + return saveChangesAsync; + } + + /// + /// 获取所有产品信息 + /// + /// + public List GetAll() + { + return context.PCategories.ToList(); + } + + /// + /// 根据id查找分类 + /// + /// Id + /// + public PCategory? GetById(Guid id) + { + return context.PCategories.Find(id); + } + + /// + /// 根据Id删除 + /// + /// 主键 + /// + public Task DeletePCategoryById(Guid? id) + { + var pCategory = new PCategory { CId = id }; + context.PCategories.Remove(pCategory); + return context.SaveChangesAsync(); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Repositories/ProductRepository.cs b/CSharp/SQLTutorial/EFCore-1-Start/Repositories/ProductRepository.cs new file mode 100644 index 0000000..004a303 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Repositories/ProductRepository.cs @@ -0,0 +1,78 @@ +using EFCore_1_Start.Context; +using EFCore_1_Start.Model; +using EFCore_1_Start.Repositories.IRepository; +using Microsoft.EntityFrameworkCore; + +namespace EFCore_1_Start.Repositories; + +/// +/// Product数据库查询 +/// +/// +public class ProductRepository(EfCoreContext context) : IProductRepository +{ + /// + /// 创建产品 + /// + /// 产品 + /// + public Task Create(Product product) + { + context.Products.Add(product); + return context.SaveChangesAsync(); + } + + /// + /// 根据id查询产品 + /// + /// Id + /// ActionResult - Product + public Task> QueryListById(Guid id) + { + return context.Products.AsNoTracking() + .Include("PCategory") + .Where(product => product.PCategoryId.Equals(id)) + .ToListAsync(); + } + + /// + /// 根据id查询产品 + /// + /// Id + /// Product + public Task GetById(Guid id) + { + return context.Products.AsNoTracking().FirstOrDefaultAsync(product => product.PId.Equals(id)); + } + + /// + /// 根据Id删除产品 + /// + /// Id + /// Task + public Task DeleteProduct(Guid id) + { + var product = new Product { PId = id }; + context.Products.Remove(product); + return context.SaveChangesAsync(); + } + + /// + /// 根据分类Id查询产品信息 + /// + /// 分类Id + /// + /// Product + public Task> QueryByKeyword(Guid cId, string keyword) + { + return context.Products.AsNoTracking() + .Include("PCategory") + .Where(p => p.PCategoryId == cId + && + p.PTitle != null + && + p.PTitle.Contains(keyword) + ) + .ToListAsync(); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Service/IPCategoryService.cs b/CSharp/SQLTutorial/EFCore-1-Start/Service/IPCategoryService.cs new file mode 100644 index 0000000..413abeb --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Service/IPCategoryService.cs @@ -0,0 +1,51 @@ +using EFCore_1_Start.Model; +using EFCore_1_Start.Repositories.IRepository; +using EFCore_1_Start.Service.IServices; + +namespace EFCore_1_Start.Service; + +/// +/// 产品分类服务 +/// +/// IPCategoryRepository +public class PCategoryService(IPCategoryRepository productRepository) : IPCategoryService +{ + /// + /// 创建产品分类 + /// + /// + /// + public Task CreatePCategory(PCategory? pCategory) + { + return productRepository.CreatePCategory(pCategory); + } + + /// + /// 获取所有产品信息 + /// + /// + public List GetAll() + { + return productRepository.GetAll(); + } + + /// + /// 根据id查找分类 + /// + /// Id + /// + public PCategory? GetById(Guid id) + { + return productRepository.GetById(id); + } + + /// + /// 根据Id删除 + /// + /// 主键 + /// + public Task DeletePCategoryById(Guid? id) + { + return productRepository.DeletePCategoryById(id); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Service/IServices/IPCategoryService.cs b/CSharp/SQLTutorial/EFCore-1-Start/Service/IServices/IPCategoryService.cs new file mode 100644 index 0000000..02a89b1 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Service/IServices/IPCategoryService.cs @@ -0,0 +1,35 @@ +using EFCore_1_Start.Model; + +namespace EFCore_1_Start.Service.IServices; + +/// +/// 产品分类接口服务 +/// +public interface IPCategoryService +{ + /// + /// 创建产品分类 + /// + /// + /// + Task CreatePCategory(PCategory? pCategory); + + /// + /// 获取所有产品信息 + /// + /// + List GetAll(); + + /// + /// 根据id查询产品 + /// + /// + PCategory? GetById(Guid id); + + /// + /// 根据Id删除 + /// + /// 主键 + /// + Task DeletePCategoryById(Guid? id); +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Service/IServices/IProductService.cs b/CSharp/SQLTutorial/EFCore-1-Start/Service/IServices/IProductService.cs new file mode 100644 index 0000000..51c3410 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Service/IServices/IProductService.cs @@ -0,0 +1,45 @@ +using EFCore_1_Start.Model; + +namespace EFCore_1_Start.Service.IServices; + +/// +/// Product服务 +/// +public interface IProductService +{ + /// + /// 创建产品 + /// + /// 产品 + /// + Task CreateProduct(Product product); + + /// + /// 根据id查询产品 + /// + /// Id + /// ActionResult - Product + Task> QueryListById(Guid id); + + /// + /// 根据id查询产品 + /// + /// Id + /// Product + Task GetById(Guid id); + + /// + /// 根据Id删除产品 + /// + /// Id + /// Task + Task DeleteProduct(Guid id); + + /// + /// 根据分类Id查询产品信息 + /// + /// 分类Id + /// + /// Product + Task> QueryByKeyword(Guid cId, string keyword); +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/Service/ProductService.cs b/CSharp/SQLTutorial/EFCore-1-Start/Service/ProductService.cs new file mode 100644 index 0000000..622e64a --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/Service/ProductService.cs @@ -0,0 +1,73 @@ +using EFCore_1_Start.Model; +using EFCore_1_Start.Repositories.IRepository; +using EFCore_1_Start.Service.IServices; + +namespace EFCore_1_Start.Service; + +/// +/// 产品服务实现 +/// +public class ProductService : IProductService +{ + private readonly IProductRepository _productRepository; + + /// + /// 产品服务构造器 + /// + /// IProductRepository + public ProductService(IProductRepository productRepository) + { + _productRepository = productRepository; + } + + /// + /// 创建产品 + /// + /// 产品 + /// + public Task CreateProduct(Product product) + { + return _productRepository.Create(product); + } + + /// + /// 根据id查询产品 + /// + /// Id + /// ActionResult - Product + public Task> QueryListById(Guid id) + { + return _productRepository.QueryListById(id); + } + + /// + /// 根据id查询产品 + /// + /// Id + /// Product + public Task GetById(Guid id) + { + return _productRepository.GetById(id); + } + + /// + /// 根据Id删除产品 + /// + /// Id + /// Task + public Task DeleteProduct(Guid id) + { + return _productRepository.DeleteProduct(id); + } + + /// + /// 根据分类Id查询产品信息 + /// + /// 分类Id + /// + /// Product + public Task> QueryByKeyword(Guid cId, string keyword) + { + return _productRepository.QueryByKeyword(cId, keyword); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-1-Start/appsettings.Development.json b/CSharp/SQLTutorial/EFCore-1-Start/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/CSharp/SQLTutorial/EFCore-1-Start/appsettings.json b/CSharp/SQLTutorial/EFCore-1-Start/appsettings.json new file mode 100644 index 0000000..e323cc6 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-1-Start/appsettings.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "ConnectionStrings": { + "BunnyTest": "Server=rm-bp12z6hlv46vi6g8mro.mysql.rds.aliyuncs.com;Port=3306;User ID=root;Password=0212zkw!;Database=test_product" + } +} diff --git a/CSharp/SQLTutorial/EFCore-2-JWT/Context/EfCoreContext.cs b/CSharp/SQLTutorial/EFCore-2-JWT/Context/EfCoreContext.cs new file mode 100644 index 0000000..ff5b52b --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-2-JWT/Context/EfCoreContext.cs @@ -0,0 +1,23 @@ +using EFCore_2_JWT.Model; +using Microsoft.EntityFrameworkCore; + +namespace EFCore_2_JWT.Context; + +/// +/// EFCore 上下文 +/// +public class EfCoreContext : DbContext +{ + /// + /// EfCoreContext 上下文 + /// + /// DbContextOptions + public EfCoreContext(DbContextOptions options) : base(options) + { + } + + /// + /// 数据库用户集合 + /// + public DbSet? Users { get; set; } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-2-JWT/Controller/UserController.cs b/CSharp/SQLTutorial/EFCore-2-JWT/Controller/UserController.cs new file mode 100644 index 0000000..466b237 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-2-JWT/Controller/UserController.cs @@ -0,0 +1,51 @@ +using EFCore_2_JWT.Model; +using EFCore_2_JWT.Service.IService; +using Microsoft.AspNetCore.Mvc; + +namespace EFCore_2_JWT.Controller; + +/// +/// 用户控制器 +/// +[Route("/api/[controller]/[action]")] +[ApiController] +public class UserController : ControllerBase +{ + private readonly IUserService _userService; + + /// + /// UserController构造器 + /// + /// + public UserController(IUserService userService) + { + _userService = userService; + } + + /// + /// 创建用户令牌 + /// + /// 用户名 + /// 密码 + /// 创建完成令牌 + [HttpGet] + public async Task CreateUserToken(string username, string password) + { + if (string.IsNullOrEmpty(username) || string.IsNullOrEmpty(password)) return NotFound(); + var userToken = await _userService.CreateUserToken(username, password); + return Ok(userToken); + } + + /// + /// 创建用户实体 + /// + /// 用户实体表单 + /// 创建成功个数 + [HttpPost] + public async Task> Create([FromBody] User? user) + { + if (user == null) return NotFound(); + + return await _userService.Create(user); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-2-JWT/EFCore-2-JWT.csproj b/CSharp/SQLTutorial/EFCore-2-JWT/EFCore-2-JWT.csproj new file mode 100644 index 0000000..234058e --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-2-JWT/EFCore-2-JWT.csproj @@ -0,0 +1,18 @@ + + + + net6.0 + enable + enable + EFCore_2_JWT + true + + + + + + + + + + diff --git a/CSharp/SQLTutorial/EFCore-2-JWT/Model/User.cs b/CSharp/SQLTutorial/EFCore-2-JWT/Model/User.cs new file mode 100644 index 0000000..a5d1bcc --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-2-JWT/Model/User.cs @@ -0,0 +1,35 @@ +using System.ComponentModel.DataAnnotations; +using System.ComponentModel.DataAnnotations.Schema; + +namespace EFCore_2_JWT.Model; + +/// +/// 用户模型对象 +/// +[Table("users")] +public class User +{ + /// + /// /主键 + /// + [Key] + public Guid? Id { get; set; } = Guid.NewGuid(); + + /// + /// 用户名 + /// + [Column("username", TypeName = "varchar(100)")] + public string? Username { get; set; } + + /// + /// 用户密码 + /// + [Column("password", TypeName = "varchar(100)")] + public string? Password { get; set; } + + /// + /// 邮箱 + /// + [Column("email", TypeName = "varchar(100)")] + public string? Email { get; set; } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-2-JWT/Program.cs b/CSharp/SQLTutorial/EFCore-2-JWT/Program.cs new file mode 100644 index 0000000..6661cb2 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-2-JWT/Program.cs @@ -0,0 +1,65 @@ +using System.Diagnostics; +using System.Reflection; +using EFCore_2_JWT.Context; +using EFCore_2_JWT.Service; +using EFCore_2_JWT.Service.IService; +using Microsoft.EntityFrameworkCore; +using Microsoft.OpenApi.Models; + +var builder = WebApplication.CreateBuilder(args); +builder.Services.AddCors(options => +{ + options.AddDefaultPolicy(policyBuilder => + { + policyBuilder.AllowAnyHeader().AllowAnyMethod().AllowAnyOrigin(); + }); +}); + +// 注册DbContext 服务 +builder.Services.AddDbContext(options => +{ + var connectionString = builder.Configuration.GetConnectionString("BunnyTest"); + options.UseMySQL(connectionString); +}); + +// Add services to the container. +builder.Services.AddControllers(); +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(c => +{ + c.SwaggerDoc("v1", new OpenApiInfo { Title = "My API", Version = "v1" }); + // ⭐ 添加 XML 注释支持 + var xmlFile = $"{Assembly.GetExecutingAssembly().GetName().Name}.xml"; + var xmlPath = Path.Combine(AppContext.BaseDirectory, xmlFile); + c.IncludeXmlComments(xmlPath); +}); + +// 依赖注入 +builder.Services.AddTransient(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.MapSwagger(); + app.UseSwaggerUI(); +} + +// 创建数据库 +using (var serviceScope = app.Services.CreateScope()) +{ + var efCoreContext = serviceScope.ServiceProvider.GetRequiredService(); + var dbCreated = efCoreContext.Database.EnsureCreatedAsync(); + Debug.WriteLine(dbCreated.Result ? "Database created successfully!" : "Database already exists."); +} + +app.UseHttpsRedirection(); + +app.UseAuthorization(); + +app.MapControllers(); + +app.Run(); \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-2-JWT/Properties/launchSettings.json b/CSharp/SQLTutorial/EFCore-2-JWT/Properties/launchSettings.json new file mode 100644 index 0000000..a58cdd6 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-2-JWT/Properties/launchSettings.json @@ -0,0 +1,31 @@ +{ + "$schema": "https://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:53710", + "sslPort": 44345 + } + }, + "profiles": { + "EFCore_2_JWT": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7297;http://localhost:5194", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/CSharp/SQLTutorial/EFCore-2-JWT/Service/IService/IUserService.cs b/CSharp/SQLTutorial/EFCore-2-JWT/Service/IService/IUserService.cs new file mode 100644 index 0000000..39fe46f --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-2-JWT/Service/IService/IUserService.cs @@ -0,0 +1,24 @@ +using EFCore_2_JWT.Model; + +namespace EFCore_2_JWT.Service.IService; + +/// +/// 用户服务接口 +/// +public interface IUserService +{ + /// + /// 创建用户实体 + /// + /// 用户实体表单 + /// 创建成功个数 + Task Create(User user); + + /// + /// 创建用户令牌 + /// + /// 用户名 + /// 密码 + /// 创建完成令牌 + Task CreateUserToken(string username, string password); +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-2-JWT/Service/UserService.cs b/CSharp/SQLTutorial/EFCore-2-JWT/Service/UserService.cs new file mode 100644 index 0000000..cca06c5 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-2-JWT/Service/UserService.cs @@ -0,0 +1,69 @@ +using System.IdentityModel.Tokens.Jwt; +using System.Security.Claims; +using System.Text; +using EFCore_2_JWT.Context; +using EFCore_2_JWT.Model; +using EFCore_2_JWT.Service.IService; +using Microsoft.CSharp.RuntimeBinder; +using Microsoft.EntityFrameworkCore; +using Microsoft.IdentityModel.Tokens; + +namespace EFCore_2_JWT.Service; + +/// +/// 用户服务对象 +/// +public class UserService : IUserService +{ + private readonly EfCoreContext _context; + + /// + /// 用户服务实现对象 + /// + /// + public UserService(EfCoreContext context) + { + _context = context; + } + + /// + /// 创建用户实体 + /// + /// 用户实体表单 + /// 创建成功个数 + public Task Create(User user) + { + _context.Users?.Add(user); + return _context.SaveChangesAsync(); + } + + /// + /// 创建用户令牌 + /// + /// 用户名 + /// 密码 + /// 创建完成令牌 + public async Task CreateUserToken(string username, string password) + { + var user = await _context.Users!.AsNoTracking() + .FirstOrDefaultAsync(user => + user.Username!.Equals(username) + && user.Password!.Equals(password)); + + if (user == null) throw new RuntimeBinderException("用户不存在"); + + var claims = new[] + { + new Claim(ClaimTypes.Sid, user.Id.ToString()!), + new Claim(ClaimTypes.Name, user.Username!) + }; + + var securityKey = new SymmetricSecurityKey(Encoding.UTF8.GetBytes("Bunny4565641145648445564545456454612541")); + var credentials = new SigningCredentials(securityKey, SecurityAlgorithms.HmacSha256); + var jwtSecurityToken = new JwtSecurityToken("issuer", "audience", claims, + expires: DateTime.Now.AddMinutes(30), + signingCredentials: credentials); + + return new JwtSecurityTokenHandler().WriteToken(jwtSecurityToken); + } +} \ No newline at end of file diff --git a/CSharp/SQLTutorial/EFCore-2-JWT/appsettings.Development.json b/CSharp/SQLTutorial/EFCore-2-JWT/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-2-JWT/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/CSharp/SQLTutorial/EFCore-2-JWT/appsettings.json b/CSharp/SQLTutorial/EFCore-2-JWT/appsettings.json new file mode 100644 index 0000000..c213a66 --- /dev/null +++ b/CSharp/SQLTutorial/EFCore-2-JWT/appsettings.json @@ -0,0 +1,12 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*", + "ConnectionStrings": { + "BunnyTest": "Server=rm-bp12z6hlv46vi6g8mro.mysql.rds.aliyuncs.com;Port=3306;User ID=root;Password=0212zkw!;Database=test_jwt" + } +} diff --git a/CSharp/SQLTutorial/SQLTutorial.sln.DotSettings.user b/CSharp/SQLTutorial/SQLTutorial.sln.DotSettings.user new file mode 100644 index 0000000..8115d7f --- /dev/null +++ b/CSharp/SQLTutorial/SQLTutorial.sln.DotSettings.user @@ -0,0 +1,10 @@ + + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + \ No newline at end of file diff --git a/CSharp/WPFTutorial/ASP-1-WebApi/ASP-1-WebApi.csproj b/CSharp/WPFTutorial/ASP-1-WebApi/ASP-1-WebApi.csproj new file mode 100644 index 0000000..413c47b --- /dev/null +++ b/CSharp/WPFTutorial/ASP-1-WebApi/ASP-1-WebApi.csproj @@ -0,0 +1,15 @@ + + + + net8.0 + enable + enable + ASP_1_WebApi + + + + + + + + diff --git a/CSharp/WPFTutorial/ASP-1-WebApi/ASP-1-WebApi.csproj.user b/CSharp/WPFTutorial/ASP-1-WebApi/ASP-1-WebApi.csproj.user new file mode 100644 index 0000000..9ff5820 --- /dev/null +++ b/CSharp/WPFTutorial/ASP-1-WebApi/ASP-1-WebApi.csproj.user @@ -0,0 +1,6 @@ + + + + https + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/ASP-1-WebApi/ASP-1-WebApi.http b/CSharp/WPFTutorial/ASP-1-WebApi/ASP-1-WebApi.http new file mode 100644 index 0000000..bbc1227 --- /dev/null +++ b/CSharp/WPFTutorial/ASP-1-WebApi/ASP-1-WebApi.http @@ -0,0 +1,6 @@ +@ASP_1_WebApi_HostAddress = http://localhost:5076 + +GET {{ASP_1_WebApi_HostAddress}}/weatherforecast/ +Accept: application/json + +### diff --git a/CSharp/WPFTutorial/ASP-1-WebApi/Program.cs b/CSharp/WPFTutorial/ASP-1-WebApi/Program.cs new file mode 100644 index 0000000..161f695 --- /dev/null +++ b/CSharp/WPFTutorial/ASP-1-WebApi/Program.cs @@ -0,0 +1,44 @@ +var builder = WebApplication.CreateBuilder(args); + +// Add services to the container. +// Learn more about configuring Swagger/OpenAPI at https://aka.ms/aspnetcore/swashbuckle +builder.Services.AddEndpointsApiExplorer(); +builder.Services.AddSwaggerGen(); + +var app = builder.Build(); + +// Configure the HTTP request pipeline. +if (app.Environment.IsDevelopment()) +{ + app.UseSwagger(); + app.UseSwaggerUI(); +} + +app.UseHttpsRedirection(); + +var summaries = new[] +{ + "Freezing", "Bracing", "Chilly", "Cool", "Mild", "Warm", "Balmy", "Hot", "Sweltering", "Scorching" +}; + +app.MapGet("/weatherforecast", () => + { + var forecast = Enumerable.Range(1, 5).Select(index => + new WeatherForecast + ( + DateOnly.FromDateTime(DateTime.Now.AddDays(index)), + Random.Shared.Next(-20, 55), + summaries[Random.Shared.Next(summaries.Length)] + )) + .ToArray(); + return forecast; + }) + .WithName("GetWeatherForecast") + .WithOpenApi(); + +app.Run(); + +record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary) +{ + public int TemperatureF => 32 + (int)(TemperatureC / 0.5556); +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/ASP-1-WebApi/Properties/launchSettings.json b/CSharp/WPFTutorial/ASP-1-WebApi/Properties/launchSettings.json new file mode 100644 index 0000000..551466e --- /dev/null +++ b/CSharp/WPFTutorial/ASP-1-WebApi/Properties/launchSettings.json @@ -0,0 +1,41 @@ +{ + "$schema": "http://json.schemastore.org/launchsettings.json", + "iisSettings": { + "windowsAuthentication": false, + "anonymousAuthentication": true, + "iisExpress": { + "applicationUrl": "http://localhost:53934", + "sslPort": 44328 + } + }, + "profiles": { + "http": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "http://localhost:5076", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "https": { + "commandName": "Project", + "dotnetRunMessages": true, + "launchBrowser": true, + "launchUrl": "swagger", + "applicationUrl": "https://localhost:7295;http://localhost:5076", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + }, + "IIS Express": { + "commandName": "IISExpress", + "launchBrowser": true, + "launchUrl": "swagger", + "environmentVariables": { + "ASPNETCORE_ENVIRONMENT": "Development" + } + } + } +} diff --git a/CSharp/WPFTutorial/ASP-1-WebApi/appsettings.Development.json b/CSharp/WPFTutorial/ASP-1-WebApi/appsettings.Development.json new file mode 100644 index 0000000..0c208ae --- /dev/null +++ b/CSharp/WPFTutorial/ASP-1-WebApi/appsettings.Development.json @@ -0,0 +1,8 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + } +} diff --git a/CSharp/WPFTutorial/ASP-1-WebApi/appsettings.json b/CSharp/WPFTutorial/ASP-1-WebApi/appsettings.json new file mode 100644 index 0000000..10f68b8 --- /dev/null +++ b/CSharp/WPFTutorial/ASP-1-WebApi/appsettings.json @@ -0,0 +1,9 @@ +{ + "Logging": { + "LogLevel": { + "Default": "Information", + "Microsoft.AspNetCore": "Warning" + } + }, + "AllowedHosts": "*" +} diff --git a/CSharp/WPFTutorial/Dialog-ModuleA/Dialog-ModuleA.csproj b/CSharp/WPFTutorial/Dialog-ModuleA/Dialog-ModuleA.csproj new file mode 100644 index 0000000..2bbcc72 --- /dev/null +++ b/CSharp/WPFTutorial/Dialog-ModuleA/Dialog-ModuleA.csproj @@ -0,0 +1,15 @@ + + + + net8.0-windows + Dialog_ModuleA + enable + enable + true + + + + + + + diff --git a/CSharp/WPFTutorial/Dialog-ModuleA/Dialog-ModuleA.csproj.user b/CSharp/WPFTutorial/Dialog-ModuleA/Dialog-ModuleA.csproj.user new file mode 100644 index 0000000..8abc76a --- /dev/null +++ b/CSharp/WPFTutorial/Dialog-ModuleA/Dialog-ModuleA.csproj.user @@ -0,0 +1,9 @@ + + + + + + Code + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dialog-ModuleA/ModuleAProfile.cs b/CSharp/WPFTutorial/Dialog-ModuleA/ModuleAProfile.cs new file mode 100644 index 0000000..db72e5f --- /dev/null +++ b/CSharp/WPFTutorial/Dialog-ModuleA/ModuleAProfile.cs @@ -0,0 +1,17 @@ +using Dialog_ModuleA.ViewModels; +using Dialog_ModuleA.Views; + +namespace Dialog_ModuleA; + +public class ModuleAProfile : IModule +{ + public void RegisterTypes(IContainerRegistry containerRegistry) + { + containerRegistry.RegisterForNavigation(); + containerRegistry.RegisterForNavigation(); + } + + public void OnInitialized(IContainerProvider containerProvider) + { + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dialog-ModuleA/ViewModels/ViewAViewModel.cs b/CSharp/WPFTutorial/Dialog-ModuleA/ViewModels/ViewAViewModel.cs new file mode 100644 index 0000000..ff2a32c --- /dev/null +++ b/CSharp/WPFTutorial/Dialog-ModuleA/ViewModels/ViewAViewModel.cs @@ -0,0 +1,5 @@ +namespace Dialog_ModuleA.ViewModels; + +public class ViewAViewModel : BindableBase +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dialog-ModuleA/ViewModels/ViewCViewModel.cs b/CSharp/WPFTutorial/Dialog-ModuleA/ViewModels/ViewCViewModel.cs new file mode 100644 index 0000000..3445bf9 --- /dev/null +++ b/CSharp/WPFTutorial/Dialog-ModuleA/ViewModels/ViewCViewModel.cs @@ -0,0 +1,43 @@ +namespace Dialog_ModuleA.ViewModels; + +public class ViewCViewModel : IDialogAware +{ + public ViewCViewModel(DialogCloseListener requestClose) + { + RequestClose = requestClose; + ConfirmCommand = new DelegateCommand(Confirm); + SaveCommand = new DelegateCommand(Save); + } + + public DelegateCommand ConfirmCommand { get; set; } + public DelegateCommand SaveCommand { get; set; } + + public string? Title { get; set; } + + public bool CanCloseDialog() + { + return true; + } + + public void OnDialogClosed() + { + var keys = new DialogParameters { { "Value", "Hello" } }; + RequestClose.Invoke(keys, ButtonResult.OK); + } + + public void OnDialogOpened(IDialogParameters parameters) + { + Title = parameters.GetValue("Value"); + } + + public DialogCloseListener RequestClose { get; } + + private void Save() + { + } + + private void Confirm() + { + RequestClose.Invoke(new DialogResult(ButtonResult.OK)); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dialog-ModuleA/Views/ViewA.xaml b/CSharp/WPFTutorial/Dialog-ModuleA/Views/ViewA.xaml new file mode 100644 index 0000000..84a7746 --- /dev/null +++ b/CSharp/WPFTutorial/Dialog-ModuleA/Views/ViewA.xaml @@ -0,0 +1,11 @@ + + + prism + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dialog-ModuleA/Views/ViewA.xaml.cs b/CSharp/WPFTutorial/Dialog-ModuleA/Views/ViewA.xaml.cs new file mode 100644 index 0000000..17d634c --- /dev/null +++ b/CSharp/WPFTutorial/Dialog-ModuleA/Views/ViewA.xaml.cs @@ -0,0 +1,11 @@ +using System.Windows.Controls; + +namespace Dialog_ModuleA.Views; + +public partial class ViewA : UserControl +{ + public ViewA() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dialog-ModuleA/Views/ViewC.xaml b/CSharp/WPFTutorial/Dialog-ModuleA/Views/ViewC.xaml new file mode 100644 index 0000000..07c3bd0 --- /dev/null +++ b/CSharp/WPFTutorial/Dialog-ModuleA/Views/ViewC.xaml @@ -0,0 +1,24 @@ + + + + + + + + + 弹窗 + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dialog-ModuleA/Views/ViewC.xaml.cs b/CSharp/WPFTutorial/Dialog-ModuleA/Views/ViewC.xaml.cs new file mode 100644 index 0000000..e98fa22 --- /dev/null +++ b/CSharp/WPFTutorial/Dialog-ModuleA/Views/ViewC.xaml.cs @@ -0,0 +1,14 @@ +using System.Windows.Controls; + +namespace Dialog_ModuleA.Views; + +/// +/// ViewB.xaml 的交互逻辑 +/// +public partial class ViewC : UserControl +{ + public ViewC() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dialog-ModuleB/Dialog-ModuleB.csproj b/CSharp/WPFTutorial/Dialog-ModuleB/Dialog-ModuleB.csproj new file mode 100644 index 0000000..db13c68 --- /dev/null +++ b/CSharp/WPFTutorial/Dialog-ModuleB/Dialog-ModuleB.csproj @@ -0,0 +1,15 @@ + + + + net8.0-windows + Dialog_ModuleB + enable + enable + true + + + + + + + diff --git a/CSharp/WPFTutorial/Dialog-ModuleB/ModuleBProfile.cs b/CSharp/WPFTutorial/Dialog-ModuleB/ModuleBProfile.cs new file mode 100644 index 0000000..b6c5c39 --- /dev/null +++ b/CSharp/WPFTutorial/Dialog-ModuleB/ModuleBProfile.cs @@ -0,0 +1,15 @@ +using Dialog_ModuleB.Views; + +namespace Dialog_ModuleB; + +public class ModuleBProfile : IModule +{ + public void RegisterTypes(IContainerRegistry containerRegistry) + { + containerRegistry.RegisterForNavigation(); + } + + public void OnInitialized(IContainerProvider containerProvider) + { + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dialog-ModuleB/Views/ViewB.xaml b/CSharp/WPFTutorial/Dialog-ModuleB/Views/ViewB.xaml new file mode 100644 index 0000000..2d0b00f --- /dev/null +++ b/CSharp/WPFTutorial/Dialog-ModuleB/Views/ViewB.xaml @@ -0,0 +1,11 @@ + + + ModuleB + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dialog-ModuleB/Views/ViewB.xaml.cs b/CSharp/WPFTutorial/Dialog-ModuleB/Views/ViewB.xaml.cs new file mode 100644 index 0000000..0be116b --- /dev/null +++ b/CSharp/WPFTutorial/Dialog-ModuleB/Views/ViewB.xaml.cs @@ -0,0 +1,11 @@ +using System.Windows.Controls; + +namespace Dialog_ModuleB.Views; + +public partial class ViewB : UserControl +{ + public ViewB() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dilog-MainApplication/App.xaml b/CSharp/WPFTutorial/Dilog-MainApplication/App.xaml new file mode 100644 index 0000000..fa7600f --- /dev/null +++ b/CSharp/WPFTutorial/Dilog-MainApplication/App.xaml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dilog-MainApplication/App.xaml.cs b/CSharp/WPFTutorial/Dilog-MainApplication/App.xaml.cs new file mode 100644 index 0000000..045560c --- /dev/null +++ b/CSharp/WPFTutorial/Dilog-MainApplication/App.xaml.cs @@ -0,0 +1,28 @@ +using System.Windows; +using Dialog_ModuleA; +using Dialog_ModuleB; +using Dilog_MainApplication.Views; + +namespace Dilog_MainApplication; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : PrismApplication +{ + protected override void RegisterTypes(IContainerRegistry containerRegistry) + { + } + + protected override Window CreateShell() + { + return Container.Resolve(); + } + + protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) + { + moduleCatalog.AddModule(); + moduleCatalog.AddModule(); + base.ConfigureModuleCatalog(moduleCatalog); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dilog-MainApplication/AssemblyInfo.cs b/CSharp/WPFTutorial/Dilog-MainApplication/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/Dilog-MainApplication/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dilog-MainApplication/Dilog-MainApplication.csproj b/CSharp/WPFTutorial/Dilog-MainApplication/Dilog-MainApplication.csproj new file mode 100644 index 0000000..463aeca --- /dev/null +++ b/CSharp/WPFTutorial/Dilog-MainApplication/Dilog-MainApplication.csproj @@ -0,0 +1,29 @@ + + + + WinExe + net8.0-windows + Dilog_MainApplication + enable + enable + true + + + + + + + + + + + + + + MSBuild:Compile + Wpf + Designer + + + + diff --git a/CSharp/WPFTutorial/Dilog-MainApplication/ViewModels/MainViewModel.cs b/CSharp/WPFTutorial/Dilog-MainApplication/ViewModels/MainViewModel.cs new file mode 100644 index 0000000..87c7ac0 --- /dev/null +++ b/CSharp/WPFTutorial/Dilog-MainApplication/ViewModels/MainViewModel.cs @@ -0,0 +1,34 @@ +namespace Dilog_MainApplication.ViewModels; + +public class MainViewModel : BindableBase +{ + private readonly IDialogService _dialogService; + private readonly IRegionManager _regionManager; + + public MainViewModel(IRegionManager regionManager, IDialogService dialogService) + { + _regionManager = regionManager; + _dialogService = dialogService; + OpenCommand = new DelegateCommand(Open); + OpenDialogCommand = new DelegateCommand(OpenDialog); + } + + public DelegateCommand OpenCommand { get; private set; } + public DelegateCommand OpenDialogCommand { get; private set; } + + private void OpenDialog(string obj) + { + var keys = new DialogParameters { { "Value", "Hello" } }; + _dialogService.ShowDialog(obj, keys, callback => + { + if (callback.Result != ButtonResult.OK) return; + var value = callback.Parameters.GetValue("Value"); + Console.WriteLine(value); + }); + } + + private void Open(string obj) + { + _regionManager.Regions["MainRegion"].RequestNavigate(obj); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dilog-MainApplication/Views/MainView.xaml b/CSharp/WPFTutorial/Dilog-MainApplication/Views/MainView.xaml new file mode 100644 index 0000000..83c648b --- /dev/null +++ b/CSharp/WPFTutorial/Dilog-MainApplication/Views/MainView.xaml @@ -0,0 +1,33 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/Dilog-MainApplication/Views/MainView.xaml.cs b/CSharp/WPFTutorial/Dilog-MainApplication/Views/MainView.xaml.cs new file mode 100644 index 0000000..4240941 --- /dev/null +++ b/CSharp/WPFTutorial/Dilog-MainApplication/Views/MainView.xaml.cs @@ -0,0 +1,14 @@ +using System.Windows; + +namespace Dilog_MainApplication.Views; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainView : Window +{ + public MainView() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/MainApplication/App.xaml b/CSharp/WPFTutorial/MainApplication/App.xaml new file mode 100644 index 0000000..5144bfc --- /dev/null +++ b/CSharp/WPFTutorial/MainApplication/App.xaml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/MainApplication/App.xaml.cs b/CSharp/WPFTutorial/MainApplication/App.xaml.cs new file mode 100644 index 0000000..03a171b --- /dev/null +++ b/CSharp/WPFTutorial/MainApplication/App.xaml.cs @@ -0,0 +1,28 @@ +using System.Windows; +using MainApplication.Views; +using ModuleA; +using ModuleB; + +namespace MainApplication; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : PrismApplication +{ + protected override void RegisterTypes(IContainerRegistry containerRegistry) + { + } + + protected override Window CreateShell() + { + return Container.Resolve(); + } + + protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) + { + moduleCatalog.AddModule(); + moduleCatalog.AddModule(); + base.ConfigureModuleCatalog(moduleCatalog); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/MainApplication/AssemblyInfo.cs b/CSharp/WPFTutorial/MainApplication/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/MainApplication/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/MainApplication/MainApplication.csproj b/CSharp/WPFTutorial/MainApplication/MainApplication.csproj new file mode 100644 index 0000000..73bda67 --- /dev/null +++ b/CSharp/WPFTutorial/MainApplication/MainApplication.csproj @@ -0,0 +1,32 @@ + + + + WinExe + net8.0-windows + enable + enable + true + + + + + + + + + + + + + + + + + + MSBuild:Compile + Wpf + Designer + + + + diff --git a/CSharp/WPFTutorial/MainApplication/ViewModels/MainViewModel.cs b/CSharp/WPFTutorial/MainApplication/ViewModels/MainViewModel.cs new file mode 100644 index 0000000..a6f2fff --- /dev/null +++ b/CSharp/WPFTutorial/MainApplication/ViewModels/MainViewModel.cs @@ -0,0 +1,19 @@ +namespace MainApplication.ViewModels; + +public class MainViewModel : BindableBase +{ + private readonly IRegionManager _regionManager; + + public MainViewModel(IRegionManager regionManager) + { + _regionManager = regionManager; + OpenCommand = new DelegateCommand(Open); + } + + public DelegateCommand OpenCommand { get; private set; } + + public void Open(string viewName) + { + _regionManager.Regions["MainRegion"].RequestNavigate(viewName); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/MainApplication/Views/MainView.xaml b/CSharp/WPFTutorial/MainApplication/Views/MainView.xaml new file mode 100644 index 0000000..79a9a05 --- /dev/null +++ b/CSharp/WPFTutorial/MainApplication/Views/MainView.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/MainApplication/Views/MainView.xaml.cs b/CSharp/WPFTutorial/MainApplication/Views/MainView.xaml.cs new file mode 100644 index 0000000..474ccdc --- /dev/null +++ b/CSharp/WPFTutorial/MainApplication/Views/MainView.xaml.cs @@ -0,0 +1,14 @@ +using System.Windows; + +namespace MainApplication.Views; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainView : Window +{ + public MainView() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Message-MainApplication/App.xaml b/CSharp/WPFTutorial/Message-MainApplication/App.xaml new file mode 100644 index 0000000..cba5a11 --- /dev/null +++ b/CSharp/WPFTutorial/Message-MainApplication/App.xaml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/Message-MainApplication/App.xaml.cs b/CSharp/WPFTutorial/Message-MainApplication/App.xaml.cs new file mode 100644 index 0000000..523fced --- /dev/null +++ b/CSharp/WPFTutorial/Message-MainApplication/App.xaml.cs @@ -0,0 +1,26 @@ +using System.Windows; +using Message_MainApplication.Views; +using Message_ModuleA; + +namespace Message_MainApplication; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : PrismApplication +{ + protected override void RegisterTypes(IContainerRegistry containerRegistry) + { + } + + protected override Window CreateShell() + { + return Container.Resolve(); + } + + protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) + { + moduleCatalog.AddModule(); + base.ConfigureModuleCatalog(moduleCatalog); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Message-MainApplication/AssemblyInfo.cs b/CSharp/WPFTutorial/Message-MainApplication/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/Message-MainApplication/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/Message-MainApplication/Message-MainApplication.csproj b/CSharp/WPFTutorial/Message-MainApplication/Message-MainApplication.csproj new file mode 100644 index 0000000..ce03c0e --- /dev/null +++ b/CSharp/WPFTutorial/Message-MainApplication/Message-MainApplication.csproj @@ -0,0 +1,28 @@ + + + + WinExe + net8.0-windows + Message_MainApplication + enable + enable + true + + + + + + + + + + + + + MSBuild:Compile + Wpf + Designer + + + + diff --git a/CSharp/WPFTutorial/Message-MainApplication/ViewModels/MainViewModel.cs b/CSharp/WPFTutorial/Message-MainApplication/ViewModels/MainViewModel.cs new file mode 100644 index 0000000..56dcf6d --- /dev/null +++ b/CSharp/WPFTutorial/Message-MainApplication/ViewModels/MainViewModel.cs @@ -0,0 +1,19 @@ +namespace Message_MainApplication.ViewModels; + +public class MainViewModel : BindableBase +{ + private readonly IRegionManager _regionManager; + + public MainViewModel(IRegionManager regionManager) + { + _regionManager = regionManager; + OpenCommand = new DelegateCommand(Open); + } + + public DelegateCommand OpenCommand { get; private set; } + + public void Open(string viewName) + { + _regionManager.Regions["MainRegion"].RequestNavigate(viewName); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Message-MainApplication/Views/MainView.xaml b/CSharp/WPFTutorial/Message-MainApplication/Views/MainView.xaml new file mode 100644 index 0000000..4e7a5a8 --- /dev/null +++ b/CSharp/WPFTutorial/Message-MainApplication/Views/MainView.xaml @@ -0,0 +1,31 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/Message-MainApplication/Views/MainView.xaml.cs b/CSharp/WPFTutorial/Message-MainApplication/Views/MainView.xaml.cs new file mode 100644 index 0000000..b69aef4 --- /dev/null +++ b/CSharp/WPFTutorial/Message-MainApplication/Views/MainView.xaml.cs @@ -0,0 +1,14 @@ +using System.Windows; + +namespace Message_MainApplication.Views; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainView : Window +{ + public MainView() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Message-ModuleA/Events/MessageEvent.cs b/CSharp/WPFTutorial/Message-ModuleA/Events/MessageEvent.cs new file mode 100644 index 0000000..b2ca9e3 --- /dev/null +++ b/CSharp/WPFTutorial/Message-ModuleA/Events/MessageEvent.cs @@ -0,0 +1,5 @@ +namespace Message_ModuleA.Events; + +public class MessageEvent : PubSubEvent +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Message-ModuleA/Message-ModuleA.csproj b/CSharp/WPFTutorial/Message-ModuleA/Message-ModuleA.csproj new file mode 100644 index 0000000..5961342 --- /dev/null +++ b/CSharp/WPFTutorial/Message-ModuleA/Message-ModuleA.csproj @@ -0,0 +1,15 @@ + + + + net8.0-windows + Message_ModuleA + enable + enable + true + + + + + + + diff --git a/CSharp/WPFTutorial/Message-ModuleA/ModuleAProfile.cs b/CSharp/WPFTutorial/Message-ModuleA/ModuleAProfile.cs new file mode 100644 index 0000000..1f5ef17 --- /dev/null +++ b/CSharp/WPFTutorial/Message-ModuleA/ModuleAProfile.cs @@ -0,0 +1,16 @@ +using Message_ModuleA.ViewModels; +using Message_ModuleA.Views; + +namespace Message_ModuleA; + +public class ModuleAProfile : IModule +{ + public void RegisterTypes(IContainerRegistry containerRegistry) + { + containerRegistry.RegisterForNavigation(); + } + + public void OnInitialized(IContainerProvider containerProvider) + { + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Message-ModuleA/ViewModels/ViewAViewModel.cs b/CSharp/WPFTutorial/Message-ModuleA/ViewModels/ViewAViewModel.cs new file mode 100644 index 0000000..5ccc1dc --- /dev/null +++ b/CSharp/WPFTutorial/Message-ModuleA/ViewModels/ViewAViewModel.cs @@ -0,0 +1,12 @@ +using Message_ModuleA.Events; + +namespace Message_ModuleA.ViewModels; + +public class ViewAViewModel : BindableBase +{ + public ViewAViewModel(DialogCloseListener requestClose, IEventAggregator aggregator) + { + // 向Message发送 + aggregator.GetEvent().Publish("Hello"); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Message-ModuleA/Views/ViewA.xaml b/CSharp/WPFTutorial/Message-ModuleA/Views/ViewA.xaml new file mode 100644 index 0000000..6556c72 --- /dev/null +++ b/CSharp/WPFTutorial/Message-ModuleA/Views/ViewA.xaml @@ -0,0 +1,11 @@ + + + 666 + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/Message-ModuleA/Views/ViewA.xaml.cs b/CSharp/WPFTutorial/Message-ModuleA/Views/ViewA.xaml.cs new file mode 100644 index 0000000..4b425eb --- /dev/null +++ b/CSharp/WPFTutorial/Message-ModuleA/Views/ViewA.xaml.cs @@ -0,0 +1,32 @@ +using System.Windows; +using System.Windows.Controls; +using Message_ModuleA.Events; + +namespace Message_ModuleA.Views; + +public partial class ViewA : UserControl +{ + private readonly IEventAggregator _eventAggregator; + + public ViewA(IEventAggregator aggregator) + { + InitializeComponent(); + _eventAggregator = aggregator; + + _eventAggregator.GetEvent().Subscribe(CloseMessage); + } + + private void CloseMessage(string message) + { + // _eventAggregator.GetEvent().Subscribe(arg => + // { + // var result = MessageBox.Show($"消息:{arg}"); + // if (result == MessageBoxResult.OK) _eventAggregator.GetEvent().Publish("确认"); + // }); + + var result = MessageBox.Show($"消息:{message}", "提示", MessageBoxButton.OKCancel); + if (result == MessageBoxResult.OK) _eventAggregator.GetEvent().Publish("确认"); + else + _eventAggregator.GetEvent().Unsubscribe(CloseMessage); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/ModuleA/ModuleA.csproj b/CSharp/WPFTutorial/ModuleA/ModuleA.csproj new file mode 100644 index 0000000..c2b3051 --- /dev/null +++ b/CSharp/WPFTutorial/ModuleA/ModuleA.csproj @@ -0,0 +1,23 @@ + + + + net8.0-windows + enable + enable + true + + + + + ..\..\..\..\..\software\Plugins\nuget\prism.core\9.0.537\lib\net6.0\Prism.dll + + + ..\..\..\..\..\software\Plugins\nuget\prism.container.abstractions\9.0.106\lib\net8.0\Prism.Container.Abstractions.dll + + + + + + + + diff --git a/CSharp/WPFTutorial/ModuleA/ModuleAProfile.cs b/CSharp/WPFTutorial/ModuleA/ModuleAProfile.cs new file mode 100644 index 0000000..0c98084 --- /dev/null +++ b/CSharp/WPFTutorial/ModuleA/ModuleAProfile.cs @@ -0,0 +1,15 @@ +using ModuleA.Views; + +namespace ModuleA; + +public class ModuleAProfile : IModule +{ + public void RegisterTypes(IContainerRegistry containerRegistry) + { + containerRegistry.RegisterForNavigation(); + } + + public void OnInitialized(IContainerProvider containerProvider) + { + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/ModuleA/Views/ViewA.xaml b/CSharp/WPFTutorial/ModuleA/Views/ViewA.xaml new file mode 100644 index 0000000..7ff2191 --- /dev/null +++ b/CSharp/WPFTutorial/ModuleA/Views/ViewA.xaml @@ -0,0 +1,11 @@ + + + ModuleA + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/ModuleA/Views/ViewA.xaml.cs b/CSharp/WPFTutorial/ModuleA/Views/ViewA.xaml.cs new file mode 100644 index 0000000..c2e86a1 --- /dev/null +++ b/CSharp/WPFTutorial/ModuleA/Views/ViewA.xaml.cs @@ -0,0 +1,11 @@ +using System.Windows.Controls; + +namespace ModuleA.Views; + +public partial class ViewA : UserControl +{ + public ViewA() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/ModuleB/ModuleB.csproj b/CSharp/WPFTutorial/ModuleB/ModuleB.csproj new file mode 100644 index 0000000..3183d9c --- /dev/null +++ b/CSharp/WPFTutorial/ModuleB/ModuleB.csproj @@ -0,0 +1,14 @@ + + + + net8.0-windows + enable + enable + true + + + + + + + diff --git a/CSharp/WPFTutorial/ModuleB/ModuleBProfile.cs b/CSharp/WPFTutorial/ModuleB/ModuleBProfile.cs new file mode 100644 index 0000000..73d838f --- /dev/null +++ b/CSharp/WPFTutorial/ModuleB/ModuleBProfile.cs @@ -0,0 +1,15 @@ +using ModuleB.Views; + +namespace ModuleB; + +public class ModuleBProfile : IModule +{ + public void RegisterTypes(IContainerRegistry containerRegistry) + { + containerRegistry.RegisterForNavigation(); + } + + public void OnInitialized(IContainerProvider containerProvider) + { + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/ModuleB/Views/ViewB.xaml b/CSharp/WPFTutorial/ModuleB/Views/ViewB.xaml new file mode 100644 index 0000000..873033a --- /dev/null +++ b/CSharp/WPFTutorial/ModuleB/Views/ViewB.xaml @@ -0,0 +1,11 @@ + + + ModuleB + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/ModuleB/Views/ViewB.xaml.cs b/CSharp/WPFTutorial/ModuleB/Views/ViewB.xaml.cs new file mode 100644 index 0000000..36feb7f --- /dev/null +++ b/CSharp/WPFTutorial/ModuleB/Views/ViewB.xaml.cs @@ -0,0 +1,11 @@ +using System.Windows.Controls; + +namespace ModuleB.Views; + +public partial class ViewB : UserControl +{ + public ViewB() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Prism-1-MainApplication/App.xaml b/CSharp/WPFTutorial/Prism-1-MainApplication/App.xaml new file mode 100644 index 0000000..9a37508 --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-MainApplication/App.xaml @@ -0,0 +1,8 @@ + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/Prism-1-MainApplication/App.xaml.cs b/CSharp/WPFTutorial/Prism-1-MainApplication/App.xaml.cs new file mode 100644 index 0000000..697dfbd --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-MainApplication/App.xaml.cs @@ -0,0 +1,28 @@ +using System.Windows; +using Prism_1_MainApplication.Views; +using Prism_1_ModuleA; +using Prism_1_ModuleB; + +namespace Prism_1_MainApplication; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : PrismApplication +{ + protected override void RegisterTypes(IContainerRegistry containerRegistry) + { + } + + protected override Window CreateShell() + { + return Container.Resolve(); + } + + protected override void ConfigureModuleCatalog(IModuleCatalog moduleCatalog) + { + moduleCatalog.AddModule(); + moduleCatalog.AddModule(); + base.ConfigureModuleCatalog(moduleCatalog); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Prism-1-MainApplication/AssemblyInfo.cs b/CSharp/WPFTutorial/Prism-1-MainApplication/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-MainApplication/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/Prism-1-MainApplication/Prism-1-MainApplication.csproj b/CSharp/WPFTutorial/Prism-1-MainApplication/Prism-1-MainApplication.csproj new file mode 100644 index 0000000..ffc2e16 --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-MainApplication/Prism-1-MainApplication.csproj @@ -0,0 +1,33 @@ + + + + WinExe + net8.0-windows + Prism_1_MainApplication + enable + enable + true + + + + + + + + + + + + + MSBuild:Compile + Wpf + Designer + + + + + + + + + diff --git a/CSharp/WPFTutorial/Prism-1-MainApplication/ViewModels/MainViewModel.cs b/CSharp/WPFTutorial/Prism-1-MainApplication/ViewModels/MainViewModel.cs new file mode 100644 index 0000000..572a5e8 --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-MainApplication/ViewModels/MainViewModel.cs @@ -0,0 +1,38 @@ +namespace Prism_1_MainApplication.ViewModels; + +public class MainViewModel : BindableBase +{ + private readonly IRegionManager _regionManager; + private IRegionNavigationJournal? _journal; + + public MainViewModel(IRegionManager regionManager) + { + _regionManager = regionManager; + OpenCommand = new DelegateCommand(Open); + BackCommand = new DelegateCommand(GoBack); + } + + public DelegateCommand OpenCommand { get; private set; } + public DelegateCommand BackCommand { get; private set; } + + private void GoBack() + { + if (_journal is { CanGoBack: true }) _journal.GoBack(); + } + + private void GoForward() + { + if (_journal is { CanGoForward: true }) _journal.GoForward(); + } + + private void Open(string obj) + { + var keys = new NavigationParameters { { "Title", "标题信息" } }; + + _regionManager.Regions["MainRegion"].RequestNavigate(obj, callback => + { + if (callback.Success && callback.Context != null) + _journal = callback.Context.NavigationService.Journal; + }, keys); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Prism-1-MainApplication/Views/MainView.xaml b/CSharp/WPFTutorial/Prism-1-MainApplication/Views/MainView.xaml new file mode 100644 index 0000000..698f68d --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-MainApplication/Views/MainView.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/Prism-1-MainApplication/Views/MainView.xaml.cs b/CSharp/WPFTutorial/Prism-1-MainApplication/Views/MainView.xaml.cs new file mode 100644 index 0000000..bd825e9 --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-MainApplication/Views/MainView.xaml.cs @@ -0,0 +1,14 @@ +using System.Windows; + +namespace Prism_1_MainApplication.Views; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainView : Window +{ + public MainView() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Prism-1-ModuleA/ModuleAProfile.cs b/CSharp/WPFTutorial/Prism-1-ModuleA/ModuleAProfile.cs new file mode 100644 index 0000000..6c28157 --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-ModuleA/ModuleAProfile.cs @@ -0,0 +1,16 @@ +using Prism_1_ModuleA.ViewModels; +using Prism_1_ModuleA.Views; + +namespace Prism_1_ModuleA; + +public class ModuleAProfile : IModule +{ + public void RegisterTypes(IContainerRegistry containerRegistry) + { + containerRegistry.RegisterForNavigation(); + } + + public void OnInitialized(IContainerProvider containerProvider) + { + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Prism-1-ModuleA/Prism-1-ModuleA.csproj b/CSharp/WPFTutorial/Prism-1-ModuleA/Prism-1-ModuleA.csproj new file mode 100644 index 0000000..08fff52 --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-ModuleA/Prism-1-ModuleA.csproj @@ -0,0 +1,15 @@ + + + + net8.0-windows + Prism_1_ModuleA + enable + enable + true + + + + + + + diff --git a/CSharp/WPFTutorial/Prism-1-ModuleA/ViewModels/ViewAModel.cs b/CSharp/WPFTutorial/Prism-1-ModuleA/ViewModels/ViewAModel.cs new file mode 100644 index 0000000..1b684ac --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-ModuleA/ViewModels/ViewAModel.cs @@ -0,0 +1,48 @@ +using System.Windows; + +namespace Prism_1_ModuleA.ViewModels; + +// public class ViewAModel : BindableBase, INavigationAware +public class ViewAModel : BindableBase, IConfirmNavigationRequest +{ + private string? _title; + + public string? Title + { + get => _title; + set + { + _title = value; + RaisePropertyChanged(); + } + } + + public void OnNavigatedTo(NavigationContext navigationContext) + { + if (navigationContext.Parameters.ContainsKey("Title")) + Title = navigationContext.Parameters.GetValue("Title"); + } + + /// + /// 是否重用原来实例 + /// + /// + /// + public bool IsNavigationTarget(NavigationContext navigationContext) + { + return true; + } + + public void OnNavigatedFrom(NavigationContext navigationContext) + { + } + + public void ConfirmNavigationRequest(NavigationContext navigationContext, Action continuationCallback) + { + var result = true; + + var boxResult = MessageBox.Show("确认导航?", "INFO", MessageBoxButton.YesNo); + if (boxResult == MessageBoxResult.No) result = false; + continuationCallback(result); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Prism-1-ModuleA/Views/ViewA.xaml b/CSharp/WPFTutorial/Prism-1-ModuleA/Views/ViewA.xaml new file mode 100644 index 0000000..b12b286 --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-ModuleA/Views/ViewA.xaml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/Prism-1-ModuleA/Views/ViewA.xaml.cs b/CSharp/WPFTutorial/Prism-1-ModuleA/Views/ViewA.xaml.cs new file mode 100644 index 0000000..86e8555 --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-ModuleA/Views/ViewA.xaml.cs @@ -0,0 +1,11 @@ +using System.Windows.Controls; + +namespace Prism_1_ModuleA.Views; + +public partial class ViewA : UserControl +{ + public ViewA() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Prism-1-ModuleB/ModuleBProfile.cs b/CSharp/WPFTutorial/Prism-1-ModuleB/ModuleBProfile.cs new file mode 100644 index 0000000..150d4d3 --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-ModuleB/ModuleBProfile.cs @@ -0,0 +1,15 @@ +using Prism_1_ModuleB.Views; + +namespace Prism_1_ModuleB; + +public class ModuleBProfile : IModule +{ + public void RegisterTypes(IContainerRegistry containerRegistry) + { + containerRegistry.RegisterForNavigation(); + } + + public void OnInitialized(IContainerProvider containerProvider) + { + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/Prism-1-ModuleB/Prism-1-ModuleB.csproj b/CSharp/WPFTutorial/Prism-1-ModuleB/Prism-1-ModuleB.csproj new file mode 100644 index 0000000..5ceb263 --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-ModuleB/Prism-1-ModuleB.csproj @@ -0,0 +1,15 @@ + + + + net8.0-windows + Prism_1_ModuleB + enable + true + enable + + + + + + + diff --git a/CSharp/WPFTutorial/Prism-1-ModuleB/Views/ViewB.xaml b/CSharp/WPFTutorial/Prism-1-ModuleB/Views/ViewB.xaml new file mode 100644 index 0000000..a655ed8 --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-ModuleB/Views/ViewB.xaml @@ -0,0 +1,11 @@ + + + ModuleB + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/Prism-1-ModuleB/Views/ViewB.xaml.cs b/CSharp/WPFTutorial/Prism-1-ModuleB/Views/ViewB.xaml.cs new file mode 100644 index 0000000..1b1d35a --- /dev/null +++ b/CSharp/WPFTutorial/Prism-1-ModuleB/Views/ViewB.xaml.cs @@ -0,0 +1,11 @@ +using System.Windows.Controls; + +namespace Prism_1_ModuleB.Views; + +public partial class ViewB : UserControl +{ + public ViewB() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/UI-1-Basics/App.xaml b/CSharp/WPFTutorial/UI-1-Basics/App.xaml new file mode 100644 index 0000000..64e7184 --- /dev/null +++ b/CSharp/WPFTutorial/UI-1-Basics/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/UI-1-Basics/App.xaml.cs b/CSharp/WPFTutorial/UI-1-Basics/App.xaml.cs new file mode 100644 index 0000000..10b92ae --- /dev/null +++ b/CSharp/WPFTutorial/UI-1-Basics/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace UI_1_Basics; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/UI-1-Basics/AssemblyInfo.cs b/CSharp/WPFTutorial/UI-1-Basics/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/UI-1-Basics/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/UI-1-Basics/MainWindow.xaml b/CSharp/WPFTutorial/UI-1-Basics/MainWindow.xaml new file mode 100644 index 0000000..550ee97 --- /dev/null +++ b/CSharp/WPFTutorial/UI-1-Basics/MainWindow.xaml @@ -0,0 +1,122 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + Raw Material + + Material + + 杀杀杀 + + + + + Manufacturing Information + Work Centres + + + + + + + + 选项1 + 选项1 + 选项1 + 选项1 + 选项1 + + + + 选项1 + 选项1 + 选项1 + 选项1 + 选项1 + + + + 长度 + + + Mess + + + Finish + + 选项1 + 选项2 + 选项3 + + + 购买信息 + + 选项1 + 选项2 + 选项3 + + + Supplier Information + + + Supplier Code + + + Additional Information + Note + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/UI-1-Basics/MainWindow.xaml.cs b/CSharp/WPFTutorial/UI-1-Basics/MainWindow.xaml.cs new file mode 100644 index 0000000..3ff2298 --- /dev/null +++ b/CSharp/WPFTutorial/UI-1-Basics/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace UI_1_Basics; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/UI-1-Basics/UI-1-Basics.csproj b/CSharp/WPFTutorial/UI-1-Basics/UI-1-Basics.csproj new file mode 100644 index 0000000..2dcd6b6 --- /dev/null +++ b/CSharp/WPFTutorial/UI-1-Basics/UI-1-Basics.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + UI_1_Basics + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-1-HelloWorld/App.xaml b/CSharp/WPFTutorial/WPF-1-HelloWorld/App.xaml new file mode 100644 index 0000000..da500ff --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-HelloWorld/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-1-HelloWorld/App.xaml.cs b/CSharp/WPFTutorial/WPF-1-HelloWorld/App.xaml.cs new file mode 100644 index 0000000..a6e32a0 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-HelloWorld/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPFTutorial; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-HelloWorld/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-1-HelloWorld/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-HelloWorld/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-HelloWorld/MainWindow.xaml b/CSharp/WPFTutorial/WPF-1-HelloWorld/MainWindow.xaml new file mode 100644 index 0000000..301ec17 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-HelloWorld/MainWindow.xaml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-HelloWorld/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-1-HelloWorld/MainWindow.xaml.cs new file mode 100644 index 0000000..94a5fa2 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-HelloWorld/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPFTutorial; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-HelloWorld/WPF-1-HelloWorld.csproj b/CSharp/WPFTutorial/WPF-1-HelloWorld/WPF-1-HelloWorld.csproj new file mode 100644 index 0000000..4da5cdb --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-HelloWorld/WPF-1-HelloWorld.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + enable + enable + true + WPFTutorial + + + diff --git a/CSharp/WPFTutorial/WPF-1-Layout/App.xaml b/CSharp/WPFTutorial/WPF-1-Layout/App.xaml new file mode 100644 index 0000000..eb34938 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Layout/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-1-Layout/App.xaml.cs b/CSharp/WPFTutorial/WPF-1-Layout/App.xaml.cs new file mode 100644 index 0000000..a5b5eb5 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Layout/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_1_Layout; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-Layout/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-1-Layout/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Layout/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-Layout/MainWindow.xaml b/CSharp/WPFTutorial/WPF-1-Layout/MainWindow.xaml new file mode 100644 index 0000000..cac8a0d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Layout/MainWindow.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-Layout/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-1-Layout/MainWindow.xaml.cs new file mode 100644 index 0000000..8361891 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Layout/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_1_Layout; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-Layout/WPF-1-Layout.csproj b/CSharp/WPFTutorial/WPF-1-Layout/WPF-1-Layout.csproj new file mode 100644 index 0000000..13204d9 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Layout/WPF-1-Layout.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_1_Layout + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-1-Start/App.xaml b/CSharp/WPFTutorial/WPF-1-Start/App.xaml new file mode 100644 index 0000000..a75cd84 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Start/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-1-Start/App.xaml.cs b/CSharp/WPFTutorial/WPF-1-Start/App.xaml.cs new file mode 100644 index 0000000..239e971 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Start/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_1_Start; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-Start/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-1-Start/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Start/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-Start/Config/ReservationException.cs b/CSharp/WPFTutorial/WPF-1-Start/Config/ReservationException.cs new file mode 100644 index 0000000..69e97a6 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Start/Config/ReservationException.cs @@ -0,0 +1,37 @@ +using System.Runtime.Serialization; +using WPF_1_Start.Models; + +namespace WPF_1_Start.Config; + +public class ReservationException : Exception +{ + public ReservationException(Reservation existingReservation, Reservation incomingReservation) + { + ExistingReservation = existingReservation; + IncomingReservation = incomingReservation; + } + + protected ReservationException(SerializationInfo info, StreamingContext context, Reservation existingReservation, + Reservation incomingReservation) : base(info, context) + { + ExistingReservation = existingReservation; + IncomingReservation = incomingReservation; + } + + public ReservationException(string? message, Reservation existingReservation, Reservation incomingReservation) : + base(message) + { + ExistingReservation = existingReservation; + IncomingReservation = incomingReservation; + } + + public ReservationException(string? message, Exception? innerException, Reservation existingReservation, + Reservation incomingReservation) : base(message, innerException) + { + ExistingReservation = existingReservation; + IncomingReservation = incomingReservation; + } + + public Reservation ExistingReservation { get; } + public Reservation IncomingReservation { get; } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-Start/MainWindow.xaml b/CSharp/WPFTutorial/WPF-1-Start/MainWindow.xaml new file mode 100644 index 0000000..62fa838 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Start/MainWindow.xaml @@ -0,0 +1,12 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-1-Start/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-1-Start/MainWindow.xaml.cs new file mode 100644 index 0000000..bfe17ed --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Start/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_1_Start; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-Start/Models/Hotel.cs b/CSharp/WPFTutorial/WPF-1-Start/Models/Hotel.cs new file mode 100644 index 0000000..5f55b28 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Start/Models/Hotel.cs @@ -0,0 +1,24 @@ +namespace WPF_1_Start.Models; + +public class Hotel +{ + private readonly ReservationBook _reservationBook; + + public Hotel(string name) + { + Name = name; + _reservationBook = new ReservationBook(); + } + + public string Name { get; set; } + + public IEnumerable GetReservationsForUser(string username) + { + return _reservationBook.GetReservations(username); + } + + public void MakeReservation(Reservation reservation) + { + _reservationBook.AddReservation(reservation); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-Start/Models/Reservation.cs b/CSharp/WPFTutorial/WPF-1-Start/Models/Reservation.cs new file mode 100644 index 0000000..6c6dd52 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Start/Models/Reservation.cs @@ -0,0 +1,24 @@ +namespace WPF_1_Start.Models; + +public class Reservation +{ + public Reservation(RoomId roomId, string? username, DateTime startTime, DateTime endTime) + { + RoomId = roomId; + Username = username; + StartTime = startTime; + EndTime = endTime; + } + + public RoomId RoomId { get; set; } + public string? Username { get; } + public DateTime StartTime { get; set; } + public DateTime EndTime { get; set; } + public TimeSpan Length => EndTime.Subtract(StartTime); + + public bool Conflicts(Reservation reservation) + { + if (!reservation.RoomId.Equals(RoomId)) return false; + return reservation.StartTime < EndTime && reservation.EndTime > StartTime; + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-Start/Models/ReservationBook.cs b/CSharp/WPFTutorial/WPF-1-Start/Models/ReservationBook.cs new file mode 100644 index 0000000..cb22ce3 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Start/Models/ReservationBook.cs @@ -0,0 +1,22 @@ +using WPF_1_Start.Config; + +namespace WPF_1_Start.Models; + +public class ReservationBook +{ + private readonly List _reservations = []; + + public IEnumerable GetReservations(string username) + { + return _reservations.Where(r => r.Username!.Equals(username)); + } + + public void AddReservation(Reservation reservation) + { + foreach (var existingReservation in _reservations.Where(existingReservation => + existingReservation.Conflicts(reservation))) + throw new ReservationException(existingReservation, reservation); + + _reservations.Add(reservation); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-Start/Models/RoomID.cs b/CSharp/WPFTutorial/WPF-1-Start/Models/RoomID.cs new file mode 100644 index 0000000..adc0856 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Start/Models/RoomID.cs @@ -0,0 +1,23 @@ +namespace WPF_1_Start.Models; + +public class RoomId +{ + public int? FloorNumber { get; } + + public int? RoomNumber { get; } + + public override bool Equals(object? obj) + { + return obj is RoomId roomId && FloorNumber == roomId.FloorNumber && RoomNumber == roomId.RoomNumber; + } + + public override int GetHashCode() + { + return HashCode.Combine(FloorNumber, RoomNumber); + } + + public override string ToString() + { + return $"{FloorNumber}{RoomNumber}"; + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-1-Start/WPF-1-Start.csproj b/CSharp/WPFTutorial/WPF-1-Start/WPF-1-Start.csproj new file mode 100644 index 0000000..01c0b63 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-1-Start/WPF-1-Start.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_1_Start + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-10-ICommand/App.xaml b/CSharp/WPFTutorial/WPF-10-ICommand/App.xaml new file mode 100644 index 0000000..51c350c --- /dev/null +++ b/CSharp/WPFTutorial/WPF-10-ICommand/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-10-ICommand/App.xaml.cs b/CSharp/WPFTutorial/WPF-10-ICommand/App.xaml.cs new file mode 100644 index 0000000..59b4bfe --- /dev/null +++ b/CSharp/WPFTutorial/WPF-10-ICommand/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_10_ICommand; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-10-ICommand/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-10-ICommand/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-10-ICommand/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-10-ICommand/MainWindow.xaml b/CSharp/WPFTutorial/WPF-10-ICommand/MainWindow.xaml new file mode 100644 index 0000000..3d513c6 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-10-ICommand/MainWindow.xaml @@ -0,0 +1,11 @@ + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-10-ICommand/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-10-ICommand/MainWindow.xaml.cs new file mode 100644 index 0000000..4a633a2 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-10-ICommand/MainWindow.xaml.cs @@ -0,0 +1,21 @@ +using System.Windows; +using WPF_10_ICommand.ViewModel; + +namespace WPF_10_ICommand; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + DataContext = new MainWindowViewModel(); + } + + private void ButtonBase_OnClick(object sender, RoutedEventArgs e) + { + MessageBox.Show("ButtonBase_OnClick"); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-10-ICommand/ViewModel/MainWindowCommand.cs b/CSharp/WPFTutorial/WPF-10-ICommand/ViewModel/MainWindowCommand.cs new file mode 100644 index 0000000..6a21f44 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-10-ICommand/ViewModel/MainWindowCommand.cs @@ -0,0 +1,25 @@ +using System.Windows.Input; + +namespace WPF_10_ICommand.ViewModel; + +public class MainWindowCommand : ICommand +{ + private readonly Action _execute; + + public MainWindowCommand(Action execute) + { + _execute = execute; + } + + public bool CanExecute(object? parameter) + { + return true; + } + + public void Execute(object? parameter) + { + _execute(); + } + + public event EventHandler? CanExecuteChanged; +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-10-ICommand/ViewModel/MainWindowViewModel.cs b/CSharp/WPFTutorial/WPF-10-ICommand/ViewModel/MainWindowViewModel.cs new file mode 100644 index 0000000..74e590f --- /dev/null +++ b/CSharp/WPFTutorial/WPF-10-ICommand/ViewModel/MainWindowViewModel.cs @@ -0,0 +1,18 @@ +using System.Windows; + +namespace WPF_10_ICommand.ViewModel; + +public class MainWindowViewModel +{ + public MainWindowViewModel() + { + Command = new MainWindowCommand(Show); + } + + public MainWindowCommand Command { get; set; } + + private void Show() + { + MessageBox.Show("ButtonBase_OnClick"); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-10-ICommand/WPF-10-ICommand.csproj b/CSharp/WPFTutorial/WPF-10-ICommand/WPF-10-ICommand.csproj new file mode 100644 index 0000000..4c3a24b --- /dev/null +++ b/CSharp/WPFTutorial/WPF-10-ICommand/WPF-10-ICommand.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_10_ICommand + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-10-OpenFileDialog/App.xaml b/CSharp/WPFTutorial/WPF-10-OpenFileDialog/App.xaml new file mode 100644 index 0000000..180edf3 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-10-OpenFileDialog/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-10-OpenFileDialog/App.xaml.cs b/CSharp/WPFTutorial/WPF-10-OpenFileDialog/App.xaml.cs new file mode 100644 index 0000000..d1ee390 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-10-OpenFileDialog/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_10_OpenFileDialog; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-10-OpenFileDialog/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-10-OpenFileDialog/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-10-OpenFileDialog/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-10-OpenFileDialog/MainWindow.xaml b/CSharp/WPFTutorial/WPF-10-OpenFileDialog/MainWindow.xaml new file mode 100644 index 0000000..5ba8ee5 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-10-OpenFileDialog/MainWindow.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-11-FolderBrowserDialog/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-11-FolderBrowserDialog/MainWindow.xaml.cs new file mode 100644 index 0000000..5bbafdc --- /dev/null +++ b/CSharp/WPFTutorial/WPF-11-FolderBrowserDialog/MainWindow.xaml.cs @@ -0,0 +1,26 @@ +using System.Windows; +using MessageBox = System.Windows.MessageBox; + +namespace WPF_11_FolderBrowserDialog; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } + + private void FireButton_OnClick(object sender, RoutedEventArgs e) + { + var folderBrowserDialog = new FolderBrowserDialog(); + folderBrowserDialog.InitialDirectory = @"D:\Project\Study\C#\WPF\6-WPF Tutorial"; + var dialogResult = folderBrowserDialog.ShowDialog(); + + if (dialogResult != System.Windows.Forms.DialogResult.OK) return; + Console.WriteLine(dialogResult); + MessageBox.Show("Folder selected: " + folderBrowserDialog.SelectedPath); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-11-FolderBrowserDialog/WPF-11-FolderBrowserDialog.csproj b/CSharp/WPFTutorial/WPF-11-FolderBrowserDialog/WPF-11-FolderBrowserDialog.csproj new file mode 100644 index 0000000..204270d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-11-FolderBrowserDialog/WPF-11-FolderBrowserDialog.csproj @@ -0,0 +1,13 @@ + + + + WinExe + net8.0-windows + WPF_11_FolderBrowserDialog + enable + enable + true + true + + + diff --git a/CSharp/WPFTutorial/WPF-12-ICommad/App.xaml b/CSharp/WPFTutorial/WPF-12-ICommad/App.xaml new file mode 100644 index 0000000..80d8534 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ICommad/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-12-ICommad/App.xaml.cs b/CSharp/WPFTutorial/WPF-12-ICommad/App.xaml.cs new file mode 100644 index 0000000..49e5f28 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ICommad/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_12_ICommad; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-12-ICommad/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-12-ICommad/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ICommad/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-12-ICommad/Command/MainWindowCommand.cs b/CSharp/WPFTutorial/WPF-12-ICommad/Command/MainWindowCommand.cs new file mode 100644 index 0000000..79dcba9 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ICommad/Command/MainWindowCommand.cs @@ -0,0 +1,25 @@ +using System.Windows.Input; + +namespace WPF_12_ICommad.Command; + +public class MainWindowCommand : ICommand +{ + private readonly Action _executeAction; + + public MainWindowCommand(Action executeAction) + { + _executeAction = executeAction; + } + + public event EventHandler? CanExecuteChanged; + + public bool CanExecute(object? parameter) + { + return true; + } + + public void Execute(object? parameter) + { + _executeAction(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-12-ICommad/MainWindow.xaml b/CSharp/WPFTutorial/WPF-12-ICommad/MainWindow.xaml new file mode 100644 index 0000000..0a833c1 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ICommad/MainWindow.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-12-ICommad/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-12-ICommad/MainWindow.xaml.cs new file mode 100644 index 0000000..982991b --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ICommad/MainWindow.xaml.cs @@ -0,0 +1,16 @@ +using System.Windows; +using WPF_12_ICommad.ViewModels; + +namespace WPF_12_ICommad; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + DataContext = new MainWindowViewModel(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-12-ICommad/ViewModels/MainWindowViewModel.cs b/CSharp/WPFTutorial/WPF-12-ICommad/ViewModels/MainWindowViewModel.cs new file mode 100644 index 0000000..cb19d51 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ICommad/ViewModels/MainWindowViewModel.cs @@ -0,0 +1,19 @@ +using System.Windows; +using WPF_12_ICommad.Command; + +namespace WPF_12_ICommad.ViewModels; + +public class MainWindowViewModel +{ + public MainWindowViewModel() + { + MainWindowCommand = new MainWindowCommand(Show); + } + + public MainWindowCommand MainWindowCommand { get; set; } + + private static void Show() + { + MessageBox.Show("点击了按钮"); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-12-ICommad/WPF-12-ICommad.csproj b/CSharp/WPFTutorial/WPF-12-ICommad/WPF-12-ICommad.csproj new file mode 100644 index 0000000..b2ebfd0 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ICommad/WPF-12-ICommad.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_12_ICommad + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-12-ListView/App.xaml b/CSharp/WPFTutorial/WPF-12-ListView/App.xaml new file mode 100644 index 0000000..6d95745 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ListView/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-12-ListView/App.xaml.cs b/CSharp/WPFTutorial/WPF-12-ListView/App.xaml.cs new file mode 100644 index 0000000..d27706c --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ListView/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_12_ListView; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-12-ListView/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-12-ListView/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ListView/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-12-ListView/MainWindow.xaml b/CSharp/WPFTutorial/WPF-12-ListView/MainWindow.xaml new file mode 100644 index 0000000..b225728 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ListView/MainWindow.xaml @@ -0,0 +1,34 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-12-ListView/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-12-ListView/MainWindow.xaml.cs new file mode 100644 index 0000000..d4b216b --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ListView/MainWindow.xaml.cs @@ -0,0 +1,60 @@ +using System.Collections; +using System.Windows; + +namespace WPF_12_ListView; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + + ListView.Items.Add("a1"); + ListView.Items.Add("a2"); + ListView.Items.Add("a3"); + ListView.Items.Add("a4"); + ListView.Items.Add("a5"); + ListView.Items.Add("a6"); + } + + private void AddButton_OnClick(object sender, RoutedEventArgs e) + { + if (string.IsNullOrEmpty(TextBox.Text)) return; + ListView.Items.Add(TextBox.Text); + + TextBox.Clear(); + } + + private void DeletedButton_OnClick(object sender, RoutedEventArgs e) + { + // 通过索引删除 + // var index = ListView.SelectedIndex; + // ListView.Items.RemoveAt(index); + + // 通过元素删除 + // var item = ListView.SelectedItem; + // var result = MessageBox.Show($"Are you sure you want to delete this ${(string)item}?", + // "Deleted?", MessageBoxButton.YesNo); + // if (result != MessageBoxResult.Yes) return; + + // 批量删除 + var items = ListView.SelectedItems; + var list = new ArrayList(items); + + if (list.Count <= 0) return; + + var result = MessageBox.Show($"Are you sure you want to delete this {list.Count}?", + "Deleted?", MessageBoxButton.YesNo); + if (result != MessageBoxResult.Yes) return; + + foreach (var item in list) ListView.Items.Remove(item); + } + + private void ClearButton_OnClick(object sender, RoutedEventArgs e) + { + ListView.Items.Clear(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-12-ListView/WPF-12-ListView.csproj b/CSharp/WPFTutorial/WPF-12-ListView/WPF-12-ListView.csproj new file mode 100644 index 0000000..4088cca --- /dev/null +++ b/CSharp/WPFTutorial/WPF-12-ListView/WPF-12-ListView.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_12_ListView + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/App.xaml b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/App.xaml new file mode 100644 index 0000000..8b1fc99 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/App.xaml.cs b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/App.xaml.cs new file mode 100644 index 0000000..10d26c3 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_13_INotifyPropertyChanged; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/Command/ShowCommand.cs b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/Command/ShowCommand.cs new file mode 100644 index 0000000..fc20849 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/Command/ShowCommand.cs @@ -0,0 +1,25 @@ +using System.Windows.Input; + +namespace WPF_13_INotifyPropertyChanged.Command; + +public class ShowCommand : ICommand +{ + private readonly Action _executeAction; + + public ShowCommand(Action executeAction) + { + _executeAction = executeAction; + } + + public bool CanExecute(object? parameter) + { + return true; + } + + public void Execute(object? parameter) + { + _executeAction(); + } + + public event EventHandler? CanExecuteChanged; +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/MainWindow.xaml b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/MainWindow.xaml new file mode 100644 index 0000000..3093fb6 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/MainWindow.xaml @@ -0,0 +1,20 @@ + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/MainWindow.xaml.cs new file mode 100644 index 0000000..ea99ee4 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/MainWindow.xaml.cs @@ -0,0 +1,16 @@ +using System.Windows; +using WPF_13_INotifyPropertyChanged.ViewModels; + +namespace WPF_13_INotifyPropertyChanged; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + DataContext = new MainWindowViewModel(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/ViewModels/MainWindowViewModel.cs b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/ViewModels/MainWindowViewModel.cs new file mode 100644 index 0000000..fef4242 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/ViewModels/MainWindowViewModel.cs @@ -0,0 +1,45 @@ +using System.Windows; +using WPF_13_INotifyPropertyChanged.Command; + +namespace WPF_13_INotifyPropertyChanged.ViewModels; + +public class MainWindowViewModel : ViewModelBase +{ + private string? _content; + + private string? _title; + + public MainWindowViewModel() + { + ShowCommand = new ShowCommand(Show); + } + + public string? Title + { + get => _title; + set + { + _title = value; + OnPropertyChanged(); + } + } + + public string? Content + { + get => _content; + set + { + _content = value; + OnPropertyChanged(); + } + } + + public ShowCommand ShowCommand { get; set; } + + private void Show() + { + Content = "Hello World"; + Title = "Hello World---Title"; + MessageBox.Show($"👼👼👼:{Content}"); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/ViewModels/ViewModelBase.cs b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/ViewModels/ViewModelBase.cs new file mode 100644 index 0000000..1b38c87 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/ViewModels/ViewModelBase.cs @@ -0,0 +1,14 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace WPF_13_INotifyPropertyChanged.ViewModels; + +public class ViewModelBase : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected void OnPropertyChanged([CallerMemberName] string propertyName = "") + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/WPF-13-INotifyPropertyChanged.csproj b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/WPF-13-INotifyPropertyChanged.csproj new file mode 100644 index 0000000..5af2c9d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-INotifyPropertyChanged/WPF-13-INotifyPropertyChanged.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_13_INotifyPropertyChanged + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-13-ObservableCollection/App.xaml b/CSharp/WPFTutorial/WPF-13-ObservableCollection/App.xaml new file mode 100644 index 0000000..7d27920 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-ObservableCollection/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-13-ObservableCollection/App.xaml.cs b/CSharp/WPFTutorial/WPF-13-ObservableCollection/App.xaml.cs new file mode 100644 index 0000000..4e6b060 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-ObservableCollection/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_13_ObservableCollection; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-13-ObservableCollection/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-13-ObservableCollection/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-ObservableCollection/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-13-ObservableCollection/MainWindow.xaml b/CSharp/WPFTutorial/WPF-13-ObservableCollection/MainWindow.xaml new file mode 100644 index 0000000..f7eaf48 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-ObservableCollection/MainWindow.xaml @@ -0,0 +1,37 @@ + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-13-ObservableCollection/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-13-ObservableCollection/MainWindow.xaml.cs new file mode 100644 index 0000000..b4a2168 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-ObservableCollection/MainWindow.xaml.cs @@ -0,0 +1,55 @@ +using System.Collections.ObjectModel; +using System.ComponentModel; +using System.Runtime.CompilerServices; +using System.Windows; + +namespace WPF_13_ObservableCollection; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : INotifyPropertyChanged +{ + private ObservableCollection _entries; + + public MainWindow() + { + DataContext = this; + _entries = ["1", "2"]; + + InitializeComponent(); + } + + public ObservableCollection Entries + { + get => _entries; + set + { + _entries = value; + OnPropertyChanged(); + } + } + + public event PropertyChangedEventHandler? PropertyChanged; + + private void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } + + private void AddButton_OnClick(object sender, RoutedEventArgs e) + { + Entries.Add(TextEntryBox.Text); + } + + private void DeleteButton_OnClick(object sender, RoutedEventArgs e) + { + var selectedItem = (string)EntriesListView.SelectedItem; + Entries.Remove(selectedItem); + } + + private void ClearButton_OnClick(object sender, RoutedEventArgs e) + { + Entries.Clear(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-13-ObservableCollection/WPF-13-ObservableCollection.csproj b/CSharp/WPFTutorial/WPF-13-ObservableCollection/WPF-13-ObservableCollection.csproj new file mode 100644 index 0000000..2ce5cd7 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-13-ObservableCollection/WPF-13-ObservableCollection.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_13_ObservableCollection + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-14-MvvmLight/App.xaml b/CSharp/WPFTutorial/WPF-14-MvvmLight/App.xaml new file mode 100644 index 0000000..3f5d66d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-MvvmLight/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-14-MvvmLight/App.xaml.cs b/CSharp/WPFTutorial/WPF-14-MvvmLight/App.xaml.cs new file mode 100644 index 0000000..c6c68bc --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-MvvmLight/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_14_MvvmLight; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-14-MvvmLight/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-14-MvvmLight/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-MvvmLight/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-14-MvvmLight/Commond/ShowCommand.cs b/CSharp/WPFTutorial/WPF-14-MvvmLight/Commond/ShowCommand.cs new file mode 100644 index 0000000..ccf5671 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-MvvmLight/Commond/ShowCommand.cs @@ -0,0 +1,25 @@ +using System.Windows.Input; + +namespace WPF_14_MvvmLight.Commond; + +public class ShowCommand : ICommand +{ + private readonly Action _executeAction; + + public ShowCommand(Action executeAction) + { + _executeAction = executeAction; + } + + public bool CanExecute(object? parameter) + { + return true; + } + + public void Execute(object? parameter) + { + _executeAction(); + } + + public event EventHandler? CanExecuteChanged; +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-14-MvvmLight/MainWindow.xaml b/CSharp/WPFTutorial/WPF-14-MvvmLight/MainWindow.xaml new file mode 100644 index 0000000..005e187 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-MvvmLight/MainWindow.xaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-14-MvvmLight/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-14-MvvmLight/MainWindow.xaml.cs new file mode 100644 index 0000000..34a024a --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-MvvmLight/MainWindow.xaml.cs @@ -0,0 +1,16 @@ +using System.Windows; +using WPF_14_MvvmLight.ViewModels; + +namespace WPF_14_MvvmLight; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + DataContext = new MainViewModel(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-14-MvvmLight/ViewModels/MainViewModel.cs b/CSharp/WPFTutorial/WPF-14-MvvmLight/ViewModels/MainViewModel.cs new file mode 100644 index 0000000..cb003d1 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-MvvmLight/ViewModels/MainViewModel.cs @@ -0,0 +1,55 @@ +using System.Windows; +using GalaSoft.MvvmLight; +using GalaSoft.MvvmLight.Command; + +namespace WPF_14_MvvmLight.ViewModels; + +public class MainViewModel : ViewModelBase +{ + private string? _content; + private string? _title; + + public MainViewModel() + { + // ShowCommand = new ShowCommand(Show); + ShowCommand = new RelayCommand(Show); + ShowArgCommand = new RelayCommand(ShowArg); + } + + // public ShowCommand ShowCommand { get; set; } + public RelayCommand ShowCommand { get; set; } + public RelayCommand ShowArgCommand { get; set; } + + public string? Title + { + get => _title; + set + { + _title = value; + RaisePropertyChanged(); + } + } + + public string? Content + { + get => _content; + set + { + _content = value; + RaisePropertyChanged(); + } + } + + private void Show() + { + Title = "Hello World"; + Content = "Hello World -- "; + MessageBox.Show("Hello World -- "); + } + + private void ShowArg(string arg) + { + Title = $"Hello World -- {arg}"; + MessageBox.Show($"Hello World -- {arg}"); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-14-MvvmLight/WPF-14-MvvmLight.csproj b/CSharp/WPFTutorial/WPF-14-MvvmLight/WPF-14-MvvmLight.csproj new file mode 100644 index 0000000..12dfe9c --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-MvvmLight/WPF-14-MvvmLight.csproj @@ -0,0 +1,16 @@ + + + + WinExe + net8.0-windows + WPF_14_MvvmLight + enable + enable + true + + + + + + + diff --git a/CSharp/WPFTutorial/WPF-14-StackPanel/App.xaml b/CSharp/WPFTutorial/WPF-14-StackPanel/App.xaml new file mode 100644 index 0000000..5d7e891 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-StackPanel/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-14-StackPanel/App.xaml.cs b/CSharp/WPFTutorial/WPF-14-StackPanel/App.xaml.cs new file mode 100644 index 0000000..469a823 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-StackPanel/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_14_StackPanel; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-14-StackPanel/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-14-StackPanel/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-StackPanel/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-14-StackPanel/MainWindow.xaml b/CSharp/WPFTutorial/WPF-14-StackPanel/MainWindow.xaml new file mode 100644 index 0000000..257ae8e --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-StackPanel/MainWindow.xaml @@ -0,0 +1,45 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-14-StackPanel/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-14-StackPanel/MainWindow.xaml.cs new file mode 100644 index 0000000..23086d2 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-StackPanel/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_14_StackPanel; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-14-StackPanel/WPF-14-StackPanel.csproj b/CSharp/WPFTutorial/WPF-14-StackPanel/WPF-14-StackPanel.csproj new file mode 100644 index 0000000..d281c29 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-14-StackPanel/WPF-14-StackPanel.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_14_StackPanel + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-15-GridSplitter/App.xaml b/CSharp/WPFTutorial/WPF-15-GridSplitter/App.xaml new file mode 100644 index 0000000..8dbb755 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-15-GridSplitter/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-15-GridSplitter/App.xaml.cs b/CSharp/WPFTutorial/WPF-15-GridSplitter/App.xaml.cs new file mode 100644 index 0000000..55f6ea7 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-15-GridSplitter/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_15_GridSplitter; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-15-GridSplitter/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-15-GridSplitter/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-15-GridSplitter/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-15-GridSplitter/MainWindow.xaml b/CSharp/WPFTutorial/WPF-15-GridSplitter/MainWindow.xaml new file mode 100644 index 0000000..291083d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-15-GridSplitter/MainWindow.xaml @@ -0,0 +1,48 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-15-GridSplitter/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-15-GridSplitter/MainWindow.xaml.cs new file mode 100644 index 0000000..c7c6c9e --- /dev/null +++ b/CSharp/WPFTutorial/WPF-15-GridSplitter/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_15_GridSplitter; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-15-GridSplitter/WPF-15-GridSplitter.csproj b/CSharp/WPFTutorial/WPF-15-GridSplitter/WPF-15-GridSplitter.csproj new file mode 100644 index 0000000..a4a1c6c --- /dev/null +++ b/CSharp/WPFTutorial/WPF-15-GridSplitter/WPF-15-GridSplitter.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_15_GridSplitter + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/App.xaml b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/App.xaml new file mode 100644 index 0000000..98ecf80 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/App.xaml.cs b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/App.xaml.cs new file mode 100644 index 0000000..4b4cb62 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_15_MvvmLightMessage; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/MainWindow.xaml b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/MainWindow.xaml new file mode 100644 index 0000000..b780eeb --- /dev/null +++ b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/MainWindow.xaml @@ -0,0 +1,22 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/MainWindow.xaml.cs new file mode 100644 index 0000000..145c1eb --- /dev/null +++ b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Windows; +using GalaSoft.MvvmLight.Messaging; +using WPF_15_MvvmLightMessage.ViewModels; + +namespace WPF_15_MvvmLightMessage; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + DataContext = new MainVIewModel(); + Messenger.Default.Register(this, "Token1", MessageToken1Sender); + } + + private void MessageToken1Sender(string value) + { + MessageBox.Show(value); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/ViewModels/MainVIewModel.cs b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/ViewModels/MainVIewModel.cs new file mode 100644 index 0000000..6538193 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/ViewModels/MainVIewModel.cs @@ -0,0 +1,22 @@ +using GalaSoft.MvvmLight; +using GalaSoft.MvvmLight.Command; +using GalaSoft.MvvmLight.Messaging; + +namespace WPF_15_MvvmLightMessage.ViewModels; + +public class MainVIewModel : ViewModelBase +{ + public MainVIewModel() + { + SendMessageCommand = new RelayCommand(SendMessage); + } + + public RelayCommand SendMessageCommand { get; set; } + + private void SendMessage(string message) + { + // MessageBox.Show("Hello World"); + Console.WriteLine("发送消息。。。"); + Messenger.Default.Send(message, "Token1"); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/WPF-15-MvvmLightMessage.csproj b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/WPF-15-MvvmLightMessage.csproj new file mode 100644 index 0000000..6d57360 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-15-MvvmLightMessage/WPF-15-MvvmLightMessage.csproj @@ -0,0 +1,16 @@ + + + + WinExe + net8.0-windows + WPF_15_MvvmLightMessage + enable + enable + true + + + + + + + diff --git a/CSharp/WPFTutorial/WPF-16-Expander/App.xaml b/CSharp/WPFTutorial/WPF-16-Expander/App.xaml new file mode 100644 index 0000000..19624db --- /dev/null +++ b/CSharp/WPFTutorial/WPF-16-Expander/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-16-Expander/App.xaml.cs b/CSharp/WPFTutorial/WPF-16-Expander/App.xaml.cs new file mode 100644 index 0000000..35d7160 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-16-Expander/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_16_Expander; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-16-Expander/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-16-Expander/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-16-Expander/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-16-Expander/MainWindow.xaml b/CSharp/WPFTutorial/WPF-16-Expander/MainWindow.xaml new file mode 100644 index 0000000..e0f1026 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-16-Expander/MainWindow.xaml @@ -0,0 +1,30 @@ + + + + + + + + + + + + 隐藏的内容 + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-16-Expander/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-16-Expander/MainWindow.xaml.cs new file mode 100644 index 0000000..6533606 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-16-Expander/MainWindow.xaml.cs @@ -0,0 +1,19 @@ +using System.Windows; + +namespace WPF_16_Expander; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } + + private void DDetailButton_OnClick(object sender, RoutedEventArgs e) + { + DetailExpander.IsExpanded = !DetailExpander.IsExpanded; + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-16-Expander/WPF-16-Expander.csproj b/CSharp/WPFTutorial/WPF-16-Expander/WPF-16-Expander.csproj new file mode 100644 index 0000000..63679c3 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-16-Expander/WPF-16-Expander.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_16_Expander + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-17-ScrollViewer/App.xaml b/CSharp/WPFTutorial/WPF-17-ScrollViewer/App.xaml new file mode 100644 index 0000000..4bafb7c --- /dev/null +++ b/CSharp/WPFTutorial/WPF-17-ScrollViewer/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-17-ScrollViewer/App.xaml.cs b/CSharp/WPFTutorial/WPF-17-ScrollViewer/App.xaml.cs new file mode 100644 index 0000000..24d1453 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-17-ScrollViewer/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_17_ScrollViewer; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-17-ScrollViewer/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-17-ScrollViewer/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-17-ScrollViewer/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-17-ScrollViewer/MainWindow.xaml b/CSharp/WPFTutorial/WPF-17-ScrollViewer/MainWindow.xaml new file mode 100644 index 0000000..599fd71 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-17-ScrollViewer/MainWindow.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-17-ScrollViewer/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-17-ScrollViewer/MainWindow.xaml.cs new file mode 100644 index 0000000..f6deea9 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-17-ScrollViewer/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_17_ScrollViewer; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-17-ScrollViewer/WPF-17-ScrollViewer.csproj b/CSharp/WPFTutorial/WPF-17-ScrollViewer/WPF-17-ScrollViewer.csproj new file mode 100644 index 0000000..cfafe74 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-17-ScrollViewer/WPF-17-ScrollViewer.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_17_ScrollViewer + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/App.xaml b/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/App.xaml new file mode 100644 index 0000000..f997750 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/App.xaml.cs b/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/App.xaml.cs new file mode 100644 index 0000000..217f605 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_18_CustomApplicationWindow; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/MainWindow.xaml b/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/MainWindow.xaml new file mode 100644 index 0000000..98889f2 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/MainWindow.xaml @@ -0,0 +1,36 @@ + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/MainWindow.xaml.cs new file mode 100644 index 0000000..238a1f2 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/MainWindow.xaml.cs @@ -0,0 +1,36 @@ +using System.Windows; +using System.Windows.Input; + +namespace WPF_18_CustomApplicationWindow; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } + + private void MainWindow_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + DragMove(); + } + + private void MinimizeButton_OnClick(object sender, RoutedEventArgs e) + { + WindowState = WindowState.Minimized; + } + + private void MaximizeButton_OnClick(object sender, RoutedEventArgs e) + { + WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized; + } + + private void CloseButton_OnClick(object sender, RoutedEventArgs e) + { + // Close(); + Application.Current.Shutdown(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/WPF-18-CustomApplicationWindow.csproj b/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/WPF-18-CustomApplicationWindow.csproj new file mode 100644 index 0000000..cbfc30d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-18-CustomApplicationWindow/WPF-18-CustomApplicationWindow.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_18_CustomApplicationWindow + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/App.xaml b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/App.xaml new file mode 100644 index 0000000..d8f9146 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/App.xaml.cs b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/App.xaml.cs new file mode 100644 index 0000000..67303f6 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_19_Opening_ustomWindowsShowShowDialog; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/MainWindow.xaml b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/MainWindow.xaml new file mode 100644 index 0000000..c426ec5 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/MainWindow.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/MainWindow.xaml.cs new file mode 100644 index 0000000..c3173bc --- /dev/null +++ b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/MainWindow.xaml.cs @@ -0,0 +1,36 @@ +using System.Windows; +using System.Windows.Input; +using WPF_19_Opening_ustomWindowsShowShowDialog.View; + +namespace WPF_19_Opening_ustomWindowsShowShowDialog; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow +{ + public MainWindow() + { + InitializeComponent(); + } + + private void NormalButton_OnClick(object sender, RoutedEventArgs e) + { + var normalWindow = new NormalWindow(); + normalWindow.Show(); + } + + private void ModalButton_OnClick(object sender, RoutedEventArgs e) + { + var modalWindow = new ModalWindow(this); + Opacity = 0.4; + modalWindow.ShowDialog(); + Opacity = 1; + if (modalWindow.Success) InputTextBox.Text = modalWindow.Message; + } + + private void MainWindow_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + DragMove(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/View/ModalWindow.xaml b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/View/ModalWindow.xaml new file mode 100644 index 0000000..5ee5d1e --- /dev/null +++ b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/View/ModalWindow.xaml @@ -0,0 +1,24 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/View/ModalWindow.xaml.cs b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/View/ModalWindow.xaml.cs new file mode 100644 index 0000000..a319597 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/View/ModalWindow.xaml.cs @@ -0,0 +1,39 @@ +using System.Windows; +using System.Windows.Controls; +using System.Windows.Input; + +namespace WPF_19_Opening_ustomWindowsShowShowDialog.View; + +public partial class ModalWindow +{ + public ModalWindow(Window parentWindow) + { + Owner = parentWindow; + InitializeComponent(); + } + + public bool Success { get; set; } + public string Message { get; set; } = string.Empty; + + private void OkButton_OnClick(object sender, RoutedEventArgs e) + { + Success = true; + Message = InputTextBox.Text; + Close(); + } + + private void CancelButton_OnClick(object sender, RoutedEventArgs e) + { + Close(); + } + + private void ModalWindow_OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e) + { + DragMove(); + } + + private void InputTextBox_OnTextChanged(object sender, TextChangedEventArgs e) + { + OkButton.IsEnabled = !string.IsNullOrEmpty(InputTextBox.Text); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/View/NormalWindow.xaml b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/View/NormalWindow.xaml new file mode 100644 index 0000000..0b48cb6 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/View/NormalWindow.xaml @@ -0,0 +1,9 @@ + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/View/NormalWindow.xaml.cs b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/View/NormalWindow.xaml.cs new file mode 100644 index 0000000..ca0863e --- /dev/null +++ b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/View/NormalWindow.xaml.cs @@ -0,0 +1,11 @@ +using System.Windows; + +namespace WPF_19_Opening_ustomWindowsShowShowDialog.View; + +public partial class NormalWindow : Window +{ + public NormalWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/WPF-19-Opening ustomWindowsShowShowDialog.csproj b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/WPF-19-Opening ustomWindowsShowShowDialog.csproj new file mode 100644 index 0000000..a013f38 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-19-Opening ustomWindowsShowShowDialog/WPF-19-Opening ustomWindowsShowShowDialog.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_19_Opening_ustomWindowsShowShowDialog + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-2-CodeBehind/App.xaml b/CSharp/WPFTutorial/WPF-2-CodeBehind/App.xaml new file mode 100644 index 0000000..869a8be --- /dev/null +++ b/CSharp/WPFTutorial/WPF-2-CodeBehind/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-2-CodeBehind/App.xaml.cs b/CSharp/WPFTutorial/WPF-2-CodeBehind/App.xaml.cs new file mode 100644 index 0000000..65155ad --- /dev/null +++ b/CSharp/WPFTutorial/WPF-2-CodeBehind/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_2_CodeBehind; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-2-CodeBehind/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-2-CodeBehind/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-2-CodeBehind/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-2-CodeBehind/MainWindow.xaml b/CSharp/WPFTutorial/WPF-2-CodeBehind/MainWindow.xaml new file mode 100644 index 0000000..e6b6c2e --- /dev/null +++ b/CSharp/WPFTutorial/WPF-2-CodeBehind/MainWindow.xaml @@ -0,0 +1,15 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-2-Grid/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-2-Grid/MainWindow.xaml.cs new file mode 100644 index 0000000..4aff389 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-2-Grid/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_2_Grid; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-2-Grid/WPF-2-Grid.csproj b/CSharp/WPFTutorial/WPF-2-Grid/WPF-2-Grid.csproj new file mode 100644 index 0000000..ab5c5e0 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-2-Grid/WPF-2-Grid.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_2_Grid + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-2-NModbus/App.xaml b/CSharp/WPFTutorial/WPF-2-NModbus/App.xaml new file mode 100644 index 0000000..c7cd1d7 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-2-NModbus/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-2-NModbus/App.xaml.cs b/CSharp/WPFTutorial/WPF-2-NModbus/App.xaml.cs new file mode 100644 index 0000000..ea6a5f3 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-2-NModbus/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_2_NModbus; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-2-NModbus/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-2-NModbus/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-2-NModbus/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-2-NModbus/MainWindow.xaml b/CSharp/WPFTutorial/WPF-2-NModbus/MainWindow.xaml new file mode 100644 index 0000000..f0b42a5 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-2-NModbus/MainWindow.xaml @@ -0,0 +1,24 @@ + + + + + + 从站id + + + 开始地址 + + + 操作内容 + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-2-NModbus/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-2-NModbus/MainWindow.xaml.cs new file mode 100644 index 0000000..c6f07ab --- /dev/null +++ b/CSharp/WPFTutorial/WPF-2-NModbus/MainWindow.xaml.cs @@ -0,0 +1,36 @@ +using System.Windows; +using WPF_2_NModbus.NModBus; + +namespace WPF_2_NModbus; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow +{ + // 修改为单例模式 + private readonly SerialPortAsync _serialPortInstance; + + public MainWindow() + { + InitializeComponent(); + // 使用单例 + _serialPortInstance ??= new SerialPortAsync("COM1"); + } + + private void ConnectButton_OnClick(object sender, RoutedEventArgs e) + { + _ = _serialPortInstance.WriteRegistersAsync(1, 1, [1]); + } + + private void WriteRegistersButton_OnClick(object sender, RoutedEventArgs e) + { + var slaveId = byte.Parse(SlaveIdTextBox.Text); + var startAddress = ushort.Parse(StartAddressTextBox.Text); + var content = Enumerable.Range(1, ushort.Parse(WirTextBox.Text)) + .Select(x => (ushort)x) + .ToArray(); + + _ = _serialPortInstance.WriteRegistersAsync(slaveId, startAddress, content); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-2-NModbus/NModBus/SerialPortAsync.cs b/CSharp/WPFTutorial/WPF-2-NModbus/NModBus/SerialPortAsync.cs new file mode 100644 index 0000000..9dd8707 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-2-NModbus/NModBus/SerialPortAsync.cs @@ -0,0 +1,91 @@ +using System.Diagnostics; +using System.IO.Ports; +using System.Windows; +using NModbus; +using NModbus.Serial; + +namespace WPF_2_NModbus.NModBus; + +public class SerialPortAsync : IDisposable +{ + private readonly string _portName; + private readonly IModbusSerialMaster _serialMaster; + private bool _disposed; + + public SerialPortAsync(string portName) + { + if (string.IsNullOrWhiteSpace(portName)) + throw new ArgumentException("端口名称不能为空", nameof(portName)); + + _portName = portName; + _serialMaster = CreateModbusSerialMaster(); + } + + public void Dispose() + { + if (_disposed) return; + _serialMaster.Dispose(); + _disposed = true; + GC.SuppressFinalize(this); + } + + /// + /// 异步写入寄存器 + /// + /// 从站ID + /// 起始地址 + /// 要写入的寄存器值 + /// 取消令牌 + /// 表示异步操作的任务 + public async Task WriteRegistersAsync(byte slaveId, ushort startAddress, ushort[] registers, + CancellationToken cancellationToken = default) + { + if (!_disposed) + try + { + await Task.Run(() => + { + cancellationToken.ThrowIfCancellationRequested(); + _serialMaster.WriteMultipleRegisters(slaveId, startAddress, registers); + }, cancellationToken).ConfigureAwait(false); + } + catch (Exception ex) + { + Console.WriteLine(ex); + Debug.WriteLine(ex); + MessageBox.Show("写入寄存器失败", "Error", MessageBoxButton.OK, MessageBoxImage.Error); + } + } + + /// + /// 创建Modbus串口主站 + /// + private IModbusSerialMaster CreateModbusSerialMaster() + { + var port = new SerialPort(_portName) + { + BaudRate = 9600, + DataBits = 8, + Parity = Parity.None, + StopBits = StopBits.One + }; + + try + { + port.Open(); + var adapter = new SerialPortAdapter(port) + { + ReadTimeout = 1000, + WriteTimeout = 1000 + }; + + var factory = new ModbusFactory(); + return factory.CreateRtuMaster(adapter); + } + catch + { + port.Dispose(); + throw; + } + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-2-NModbus/WPF-2-NModbus.csproj b/CSharp/WPFTutorial/WPF-2-NModbus/WPF-2-NModbus.csproj new file mode 100644 index 0000000..3bfab90 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-2-NModbus/WPF-2-NModbus.csproj @@ -0,0 +1,16 @@ + + + + WinExe + net8.0-windows + WPF_2_NModbus + enable + enable + true + + + + + + + diff --git a/CSharp/WPFTutorial/WPF-20-ReusableStyleResources/App.xaml b/CSharp/WPFTutorial/WPF-20-ReusableStyleResources/App.xaml new file mode 100644 index 0000000..f9afdcb --- /dev/null +++ b/CSharp/WPFTutorial/WPF-20-ReusableStyleResources/App.xaml @@ -0,0 +1,13 @@ + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-20-ReusableStyleResources/App.xaml.cs b/CSharp/WPFTutorial/WPF-20-ReusableStyleResources/App.xaml.cs new file mode 100644 index 0000000..b936262 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-20-ReusableStyleResources/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_20_ReusableStyleResources; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-20-ReusableStyleResources/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-20-ReusableStyleResources/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-20-ReusableStyleResources/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-20-ReusableStyleResources/MainWindow.xaml b/CSharp/WPFTutorial/WPF-20-ReusableStyleResources/MainWindow.xaml new file mode 100644 index 0000000..7c72616 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-20-ReusableStyleResources/MainWindow.xaml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-21-StylesandControlTemplates/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-21-StylesandControlTemplates/MainWindow.xaml.cs new file mode 100644 index 0000000..706c127 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-21-StylesandControlTemplates/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_21_StylesandControlTemplates; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-21-StylesandControlTemplates/WPF-21-StylesandControlTemplates.csproj b/CSharp/WPFTutorial/WPF-21-StylesandControlTemplates/WPF-21-StylesandControlTemplates.csproj new file mode 100644 index 0000000..f958000 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-21-StylesandControlTemplates/WPF-21-StylesandControlTemplates.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_21_StylesandControlTemplates + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-22-MVVMViewModels/App.xaml b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/App.xaml new file mode 100644 index 0000000..fcd9875 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-22-MVVMViewModels/App.xaml.cs b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/App.xaml.cs new file mode 100644 index 0000000..2d9a6fe --- /dev/null +++ b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_23_MVVMViewModels; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-22-MVVMViewModels/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-22-MVVMViewModels/MVVM/ViewModelBase.cs b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/MVVM/ViewModelBase.cs new file mode 100644 index 0000000..973b983 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/MVVM/ViewModelBase.cs @@ -0,0 +1,14 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace WPF_23_MVVMViewModels.MVVM; + +public class ViewModelBase : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-22-MVVMViewModels/MainWindow.xaml b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/MainWindow.xaml new file mode 100644 index 0000000..5046cbf --- /dev/null +++ b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/MainWindow.xaml @@ -0,0 +1,41 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-22-MVVMViewModels/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/MainWindow.xaml.cs new file mode 100644 index 0000000..04a8f62 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/MainWindow.xaml.cs @@ -0,0 +1,17 @@ +using System.Windows; +using WPF_23_MVVMViewModels.ViewModel; + +namespace WPF_23_MVVMViewModels; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + var windowViewModel = new MainWindowViewModel(); + DataContext = windowViewModel; + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-22-MVVMViewModels/Model/Item.cs b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/Model/Item.cs new file mode 100644 index 0000000..cee1622 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/Model/Item.cs @@ -0,0 +1,8 @@ +namespace WPF_23_MVVMViewModels.Model; + +public class Item +{ + public string? Name { get; set; } + public string? SerialNUmber { get; set; } + public int Quantity { get; set; } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-22-MVVMViewModels/ViewModel/MainWindowViewModel.cs b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/ViewModel/MainWindowViewModel.cs new file mode 100644 index 0000000..41be5dd --- /dev/null +++ b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/ViewModel/MainWindowViewModel.cs @@ -0,0 +1,27 @@ +using System.Collections.ObjectModel; +using WPF_23_MVVMViewModels.Model; +using WPF_23_MVVMViewModels.MVVM; + +namespace WPF_23_MVVMViewModels.ViewModel; + +public class MainWindowViewModel : ViewModelBase +{ + private Item? _selectedItem; + + public ObservableCollection Items { get; set; } = + [ + new() { Name = "Product1", SerialNUmber = "0001", Quantity = 5 }, + new() { Name = "Product2", SerialNUmber = "0002", Quantity = 6 } + ]; + + + public Item SelectedItem + { + get => _selectedItem!; + set + { + _selectedItem = value; + OnPropertyChanged(); + } + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-22-MVVMViewModels/WPF-22-MVVMViewModels.csproj b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/WPF-22-MVVMViewModels.csproj new file mode 100644 index 0000000..391e3b4 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-22-MVVMViewModels/WPF-22-MVVMViewModels.csproj @@ -0,0 +1,16 @@ + + + + WinExe + net8.0-windows + WPF_23_MVVMViewModels + enable + enable + true + + + + + + + diff --git a/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/App.xaml b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/App.xaml new file mode 100644 index 0000000..18bfc12 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/App.xaml.cs b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/App.xaml.cs new file mode 100644 index 0000000..fe41216 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_23_MVVMRelayCommand; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/MVVM/RelayCommand.cs b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/MVVM/RelayCommand.cs new file mode 100644 index 0000000..874b99b --- /dev/null +++ b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/MVVM/RelayCommand.cs @@ -0,0 +1,31 @@ +using System.Windows.Input; + +namespace WPF_23_MVVMRelayCommand.MVVM; + +public class RelayCommand : ICommand +{ + private readonly Action _execute; + private readonly Func? _canExecute; + + public RelayCommand(Action execute, Func? canExecute = null) + { + _execute = execute; + _canExecute = canExecute; + } + + public event EventHandler? CanExecuteChanged + { + add => CommandManager.RequerySuggested += value; + remove => CommandManager.RequerySuggested -= value; + } + + public bool CanExecute(object? parameter) + { + return _canExecute == null || _canExecute(parameter!); + } + + public void Execute(object? parameter) + { + _execute(parameter!); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/MVVM/ViewModelBase.cs b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/MVVM/ViewModelBase.cs new file mode 100644 index 0000000..b516422 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/MVVM/ViewModelBase.cs @@ -0,0 +1,14 @@ +using System.ComponentModel; +using System.Runtime.CompilerServices; + +namespace WPF_23_MVVMRelayCommand.MVVM; + +public class ViewModelBase : INotifyPropertyChanged +{ + public event PropertyChangedEventHandler? PropertyChanged; + + protected void OnPropertyChanged([CallerMemberName] string? propertyName = null) + { + PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName)); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/MainWindow.xaml b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/MainWindow.xaml new file mode 100644 index 0000000..dbb3038 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/MainWindow.xaml @@ -0,0 +1,50 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/MainWindow.xaml.cs new file mode 100644 index 0000000..779f596 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/MainWindow.xaml.cs @@ -0,0 +1,16 @@ +using System.Windows; +using WPF_23_MVVMRelayCommand.ViewModel; + +namespace WPF_23_MVVMRelayCommand; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + DataContext = new MainWindowViewModel(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/Model/Item.cs b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/Model/Item.cs new file mode 100644 index 0000000..b9ab35c --- /dev/null +++ b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/Model/Item.cs @@ -0,0 +1,8 @@ +namespace WPF_23_MVVMRelayCommand.Model; + +public class Item +{ + public string? Name { get; set; } + public string? SerialNUmber { get; set; } + public int Quantity { get; set; } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/ViewModel/MainWindowViewModel.cs b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/ViewModel/MainWindowViewModel.cs new file mode 100644 index 0000000..ab9cda2 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/ViewModel/MainWindowViewModel.cs @@ -0,0 +1,51 @@ +using System.Collections.ObjectModel; +using WPF_23_MVVMRelayCommand.Model; +using WPF_23_MVVMRelayCommand.MVVM; + +namespace WPF_23_MVVMRelayCommand.ViewModel; + +public class MainWindowViewModel : ViewModelBase +{ + private Item? _selectedItem; + + public RelayCommand AddCommand => new(execute => AddItem(), canExecute => true); + public RelayCommand DeleteCommand => new(execute => DeleteItem(), canExecute => SelectedItem != null); + public RelayCommand SaveCommand => new(execute => SaveItem(), canExecute => CanSave()); + + public ObservableCollection Items { get; set; } = + [ + new() { Name = "Product1", SerialNUmber = "0001", Quantity = 5 }, + new() { Name = "Product2", SerialNUmber = "0002", Quantity = 6 } + ]; + + + public Item? SelectedItem + { + get => _selectedItem; + set + { + _selectedItem = value; + OnPropertyChanged(); + } + } + + private void AddItem() + { + Items.Add(new Item { Name = "NEW ITEM", SerialNUmber = "0001", Quantity = 5 }); + } + + private void DeleteItem() + { + Items.Remove(SelectedItem!); + } + + private void SaveItem() + { + // Save + } + + private bool CanSave() + { + return true; + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/WPF-23-MVVMRelayCommand.csproj b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/WPF-23-MVVMRelayCommand.csproj new file mode 100644 index 0000000..3a7530c --- /dev/null +++ b/CSharp/WPFTutorial/WPF-23-MVVMRelayCommand/WPF-23-MVVMRelayCommand.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_23_MVVMRelayCommand + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-24-Controls/App.xaml b/CSharp/WPFTutorial/WPF-24-Controls/App.xaml new file mode 100644 index 0000000..8eed269 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-24-Controls/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-24-Controls/App.xaml.cs b/CSharp/WPFTutorial/WPF-24-Controls/App.xaml.cs new file mode 100644 index 0000000..34d70fd --- /dev/null +++ b/CSharp/WPFTutorial/WPF-24-Controls/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_24_Controls; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-24-Controls/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-24-Controls/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-24-Controls/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-24-Controls/Assets/java-big.png b/CSharp/WPFTutorial/WPF-24-Controls/Assets/java-big.png new file mode 100644 index 0000000..80abba7 Binary files /dev/null and b/CSharp/WPFTutorial/WPF-24-Controls/Assets/java-big.png differ diff --git a/CSharp/WPFTutorial/WPF-24-Controls/MainWindow.xaml b/CSharp/WPFTutorial/WPF-24-Controls/MainWindow.xaml new file mode 100644 index 0000000..4a00bbb --- /dev/null +++ b/CSharp/WPFTutorial/WPF-24-Controls/MainWindow.xaml @@ -0,0 +1,61 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-26-MVVM/Views/MainView.xaml.cs b/CSharp/WPFTutorial/WPF-26-MVVM/Views/MainView.xaml.cs new file mode 100644 index 0000000..c2e0764 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-26-MVVM/Views/MainView.xaml.cs @@ -0,0 +1,14 @@ +using System.Windows; + +namespace WPF_26_MVVM.Views; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainView : Window +{ + public MainView() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewA.xaml b/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewA.xaml new file mode 100644 index 0000000..2e19d45 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewA.xaml @@ -0,0 +1,11 @@ + + + AAAA + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewA.xaml.cs b/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewA.xaml.cs new file mode 100644 index 0000000..9836a5b --- /dev/null +++ b/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewA.xaml.cs @@ -0,0 +1,11 @@ +using System.Windows.Controls; + +namespace WPF_26_MVVM.Views; + +public partial class ViewA : UserControl +{ + public ViewA() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewB.xaml b/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewB.xaml new file mode 100644 index 0000000..0d6041b --- /dev/null +++ b/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewB.xaml @@ -0,0 +1,11 @@ + + + BBBBBB + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewB.xaml.cs b/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewB.xaml.cs new file mode 100644 index 0000000..65c8790 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewB.xaml.cs @@ -0,0 +1,11 @@ +using System.Windows.Controls; + +namespace WPF_26_MVVM.Views; + +public partial class ViewB : UserControl +{ + public ViewB() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewC.xaml b/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewC.xaml new file mode 100644 index 0000000..df3cd2e --- /dev/null +++ b/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewC.xaml @@ -0,0 +1,11 @@ + + + CCCC + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewC.xaml.cs b/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewC.xaml.cs new file mode 100644 index 0000000..df39fc2 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-26-MVVM/Views/ViewC.xaml.cs @@ -0,0 +1,11 @@ +using System.Windows.Controls; + +namespace WPF_26_MVVM.Views; + +public partial class ViewC : UserControl +{ + public ViewC() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-26-MVVM/WPF-26-MVVM.csproj b/CSharp/WPFTutorial/WPF-26-MVVM/WPF-26-MVVM.csproj new file mode 100644 index 0000000..5d2fb44 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-26-MVVM/WPF-26-MVVM.csproj @@ -0,0 +1,29 @@ + + + + WinExe + net8.0-windows + WPF_26_MVVM + enable + enable + true + + + + + + + + + + + + + + MSBuild:Compile + Wpf + Designer + + + + diff --git a/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/App.xaml b/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/App.xaml new file mode 100644 index 0000000..ab8e57a --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/App.xaml.cs b/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/App.xaml.cs new file mode 100644 index 0000000..a6dab3c --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_3_Grid_BasicResponsiveLayouts; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/MainWindow.xaml b/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/MainWindow.xaml new file mode 100644 index 0000000..a3b9709 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/MainWindow.xaml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/MainWindow.xaml.cs new file mode 100644 index 0000000..350e467 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_3_Grid_BasicResponsiveLayouts; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/WPF-3-Grid-BasicResponsiveLayouts.csproj b/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/WPF-3-Grid-BasicResponsiveLayouts.csproj new file mode 100644 index 0000000..3311f8c --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Grid-BasicResponsiveLayouts/WPF-3-Grid-BasicResponsiveLayouts.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_3_Grid_BasicResponsiveLayouts + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-3-Grid-Layout/App.xaml b/CSharp/WPFTutorial/WPF-3-Grid-Layout/App.xaml new file mode 100644 index 0000000..abf6887 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Grid-Layout/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-3-Grid-Layout/App.xaml.cs b/CSharp/WPFTutorial/WPF-3-Grid-Layout/App.xaml.cs new file mode 100644 index 0000000..b1de883 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Grid-Layout/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_3_Grid_Layout; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-Grid-Layout/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-3-Grid-Layout/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Grid-Layout/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-Grid-Layout/MainWindow.xaml b/CSharp/WPFTutorial/WPF-3-Grid-Layout/MainWindow.xaml new file mode 100644 index 0000000..d48da59 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Grid-Layout/MainWindow.xaml @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-Grid-Layout/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-3-Grid-Layout/MainWindow.xaml.cs new file mode 100644 index 0000000..73d9f2e --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Grid-Layout/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_3_Grid_Layout; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-Grid-Layout/WPF-3-Grid-Layout.csproj b/CSharp/WPFTutorial/WPF-3-Grid-Layout/WPF-3-Grid-Layout.csproj new file mode 100644 index 0000000..0ac0a16 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Grid-Layout/WPF-3-Grid-Layout.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_3_Grid_Layout + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-3-GridSPan/App.xaml b/CSharp/WPFTutorial/WPF-3-GridSPan/App.xaml new file mode 100644 index 0000000..02996ca --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-GridSPan/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-3-GridSPan/App.xaml.cs b/CSharp/WPFTutorial/WPF-3-GridSPan/App.xaml.cs new file mode 100644 index 0000000..1f9dbe1 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-GridSPan/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_3_GridSPan; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-GridSPan/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-3-GridSPan/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-GridSPan/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-GridSPan/MainWindow.xaml b/CSharp/WPFTutorial/WPF-3-GridSPan/MainWindow.xaml new file mode 100644 index 0000000..4b2c267 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-GridSPan/MainWindow.xaml @@ -0,0 +1,21 @@ + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-GridSPan/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-3-GridSPan/MainWindow.xaml.cs new file mode 100644 index 0000000..503bc52 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-GridSPan/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_3_GridSPan; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-GridSPan/WPF-3-GridSPan.csproj b/CSharp/WPFTutorial/WPF-3-GridSPan/WPF-3-GridSPan.csproj new file mode 100644 index 0000000..c676fb0 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-GridSPan/WPF-3-GridSPan.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_3_GridSPan + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-3-Sample/App.xaml b/CSharp/WPFTutorial/WPF-3-Sample/App.xaml new file mode 100644 index 0000000..6d6a056 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Sample/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-3-Sample/App.xaml.cs b/CSharp/WPFTutorial/WPF-3-Sample/App.xaml.cs new file mode 100644 index 0000000..c28d00b --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Sample/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_3_Sample; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-Sample/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-3-Sample/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Sample/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-Sample/MainWindow.xaml b/CSharp/WPFTutorial/WPF-3-Sample/MainWindow.xaml new file mode 100644 index 0000000..8e2fe78 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Sample/MainWindow.xaml @@ -0,0 +1,52 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-Sample/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-3-Sample/MainWindow.xaml.cs new file mode 100644 index 0000000..3c55290 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Sample/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_3_Sample; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-3-Sample/WPF-3-Sample.csproj b/CSharp/WPFTutorial/WPF-3-Sample/WPF-3-Sample.csproj new file mode 100644 index 0000000..0b2f272 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-3-Sample/WPF-3-Sample.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_3_Sample + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/App.xaml b/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/App.xaml new file mode 100644 index 0000000..4091b0d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/App.xaml.cs b/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/App.xaml.cs new file mode 100644 index 0000000..384608e --- /dev/null +++ b/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_4_Custom_User_Controls; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/MainWindow.xaml b/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/MainWindow.xaml new file mode 100644 index 0000000..6ebe23c --- /dev/null +++ b/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/MainWindow.xaml @@ -0,0 +1,19 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/MainWindow.xaml.cs new file mode 100644 index 0000000..5310550 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_4_Custom_User_Controls; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/View/UserController/MenuBar.xaml b/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/View/UserController/MenuBar.xaml new file mode 100644 index 0000000..f1c025d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-4-Custom-User-Controls/View/UserController/MenuBar.xaml @@ -0,0 +1,32 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-5-UniformGrid/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-5-UniformGrid/MainWindow.xaml.cs new file mode 100644 index 0000000..2a38ca6 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-5-UniformGrid/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_5_UniformGrid; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-5-UniformGrid/WPF-5-UniformGrid.csproj b/CSharp/WPFTutorial/WPF-5-UniformGrid/WPF-5-UniformGrid.csproj new file mode 100644 index 0000000..67ff49e --- /dev/null +++ b/CSharp/WPFTutorial/WPF-5-UniformGrid/WPF-5-UniformGrid.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_5_UniformGrid + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-6-Style/App.xaml b/CSharp/WPFTutorial/WPF-6-Style/App.xaml new file mode 100644 index 0000000..aac4c12 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-6-Style/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-6-Style/App.xaml.cs b/CSharp/WPFTutorial/WPF-6-Style/App.xaml.cs new file mode 100644 index 0000000..069333c --- /dev/null +++ b/CSharp/WPFTutorial/WPF-6-Style/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_6_Style; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-6-Style/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-6-Style/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-6-Style/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-6-Style/MainWindow.xaml b/CSharp/WPFTutorial/WPF-6-Style/MainWindow.xaml new file mode 100644 index 0000000..cc22808 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-6-Style/MainWindow.xaml @@ -0,0 +1,43 @@ + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-8-DataGrid/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-8-DataGrid/MainWindow.xaml.cs new file mode 100644 index 0000000..6353222 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-8-DataGrid/MainWindow.xaml.cs @@ -0,0 +1,36 @@ +using System.Collections; +using System.Windows; + +namespace WPF_8_DataGrid; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + var arrayList = new ArrayList(); + + for (var i = 0; i < 100; i++) + { + var randomNum = Random.Shared.NextInt64(0, 999); + var name = (i * randomNum).ToString("x6"); + Console.WriteLine(name); + arrayList.Add(new Color + { + Name = name, + Code = $"#{name}" + }); + } + + Grid.ItemsSource = arrayList; + } +} + +public class Color +{ + public string? Code { get; set; } + public string? Name { get; set; } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-8-DataGrid/WPF-8-DataGrid.csproj b/CSharp/WPFTutorial/WPF-8-DataGrid/WPF-8-DataGrid.csproj new file mode 100644 index 0000000..6d977d6 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-8-DataGrid/WPF-8-DataGrid.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_8_DataGrid + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-9-MessageBox/App.xaml b/CSharp/WPFTutorial/WPF-9-MessageBox/App.xaml new file mode 100644 index 0000000..f6dcda4 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-9-MessageBox/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-9-MessageBox/App.xaml.cs b/CSharp/WPFTutorial/WPF-9-MessageBox/App.xaml.cs new file mode 100644 index 0000000..8dbfa66 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-9-MessageBox/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_9_MessageBox; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-9-MessageBox/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-9-MessageBox/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-9-MessageBox/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-9-MessageBox/MainWindow.xaml b/CSharp/WPFTutorial/WPF-9-MessageBox/MainWindow.xaml new file mode 100644 index 0000000..9c4e4c3 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-9-MessageBox/MainWindow.xaml @@ -0,0 +1,18 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-9-MessageBox/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-9-MessageBox/MainWindow.xaml.cs new file mode 100644 index 0000000..fe0fbfe --- /dev/null +++ b/CSharp/WPFTutorial/WPF-9-MessageBox/MainWindow.xaml.cs @@ -0,0 +1,20 @@ +using System.Windows; + +namespace WPF_9_MessageBox; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } + + private void FireButton_OnClick(object sender, RoutedEventArgs e) + { + var result = MessageBox.Show("You Message Here.", "Error", MessageBoxButton.YesNo, MessageBoxImage.Question); + InfoTextBlock.Text = result == MessageBoxResult.Yes ? "Agree" : "Not Agree"; + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-9-MessageBox/WPF-9-MessageBox.csproj b/CSharp/WPFTutorial/WPF-9-MessageBox/WPF-9-MessageBox.csproj new file mode 100644 index 0000000..bdecf0e --- /dev/null +++ b/CSharp/WPFTutorial/WPF-9-MessageBox/WPF-9-MessageBox.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_9_MessageBox + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPF-9-元素绑定元素/App.xaml b/CSharp/WPFTutorial/WPF-9-元素绑定元素/App.xaml new file mode 100644 index 0000000..ef471d9 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-9-元素绑定元素/App.xaml @@ -0,0 +1,9 @@ + + + + + diff --git a/CSharp/WPFTutorial/WPF-9-元素绑定元素/App.xaml.cs b/CSharp/WPFTutorial/WPF-9-元素绑定元素/App.xaml.cs new file mode 100644 index 0000000..37734c8 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-9-元素绑定元素/App.xaml.cs @@ -0,0 +1,12 @@ +using System.Configuration; +using System.Data; +using System.Windows; + +namespace WPF_9_元素绑定元素; + +/// +/// Interaction logic for App.xaml +/// +public partial class App : Application +{ +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-9-元素绑定元素/AssemblyInfo.cs b/CSharp/WPFTutorial/WPF-9-元素绑定元素/AssemblyInfo.cs new file mode 100644 index 0000000..4a05c7d --- /dev/null +++ b/CSharp/WPFTutorial/WPF-9-元素绑定元素/AssemblyInfo.cs @@ -0,0 +1,10 @@ +using System.Windows; + +[assembly: ThemeInfo( + ResourceDictionaryLocation.None, //where theme specific resource dictionaries are located + //(used if a resource is not found in the page, + // or application resource dictionaries) + ResourceDictionaryLocation.SourceAssembly //where the generic resource dictionary is located + //(used if a resource is not found in the page, + // app, or any theme specific resource dictionaries) +)] \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-9-元素绑定元素/MainWindow.xaml b/CSharp/WPFTutorial/WPF-9-元素绑定元素/MainWindow.xaml new file mode 100644 index 0000000..24d7085 --- /dev/null +++ b/CSharp/WPFTutorial/WPF-9-元素绑定元素/MainWindow.xaml @@ -0,0 +1,15 @@ + + + + + + + + + \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-9-元素绑定元素/MainWindow.xaml.cs b/CSharp/WPFTutorial/WPF-9-元素绑定元素/MainWindow.xaml.cs new file mode 100644 index 0000000..a7949cb --- /dev/null +++ b/CSharp/WPFTutorial/WPF-9-元素绑定元素/MainWindow.xaml.cs @@ -0,0 +1,23 @@ +using System.Text; +using System.Windows; +using System.Windows.Controls; +using System.Windows.Data; +using System.Windows.Documents; +using System.Windows.Input; +using System.Windows.Media; +using System.Windows.Media.Imaging; +using System.Windows.Navigation; +using System.Windows.Shapes; + +namespace WPF_9_元素绑定元素; + +/// +/// Interaction logic for MainWindow.xaml +/// +public partial class MainWindow : Window +{ + public MainWindow() + { + InitializeComponent(); + } +} \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPF-9-元素绑定元素/WPF-9-元素绑定元素.csproj b/CSharp/WPFTutorial/WPF-9-元素绑定元素/WPF-9-元素绑定元素.csproj new file mode 100644 index 0000000..47c8f4e --- /dev/null +++ b/CSharp/WPFTutorial/WPF-9-元素绑定元素/WPF-9-元素绑定元素.csproj @@ -0,0 +1,12 @@ + + + + WinExe + net8.0-windows + WPF_9_元素绑定元素 + enable + enable + true + + + diff --git a/CSharp/WPFTutorial/WPFTutorial.sln.DotSettings b/CSharp/WPFTutorial/WPFTutorial.sln.DotSettings new file mode 100644 index 0000000..3d8771c --- /dev/null +++ b/CSharp/WPFTutorial/WPFTutorial.sln.DotSettings @@ -0,0 +1,2 @@ + + False \ No newline at end of file diff --git a/CSharp/WPFTutorial/WPFTutorial.sln.DotSettings.user b/CSharp/WPFTutorial/WPFTutorial.sln.DotSettings.user new file mode 100644 index 0000000..55066c3 --- /dev/null +++ b/CSharp/WPFTutorial/WPFTutorial.sln.DotSettings.user @@ -0,0 +1,17 @@ + + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded + ForceIncluded \ No newline at end of file