今天,也是刚刚答完辩,终于可以将自己写的代码放到CSDN上啦,这个是开学之前就做好的一个项目,然后就是简单的使用winform做了一个CS结构的课设,实现了基础的crud以及扩展的导入导出Excel和图表控件及高德地图天气API接口的使用。使用了一些基本的控件和特殊一点的控件就是ImageList 和 listView (因为我们课上没有学过,所以觉得比较特殊)
然后下面的话,是整体项目的一个结构(简单分了一下包,DataAccess就是数据接入层dao,Entity就是对应的一些实体类,Resources是项目的一些静态资源,Utils下的话是我自己做的一些工具类,Views的是winform一些不同功能的窗体区分)
登录首页
这里的话,实现了一个侧边栏的封装和自定义最小化和最大化按钮,然后中间主体是一个高德地图的天气API,具体使用我会在后面的文章列出,然后还有个底部的计时器实现时间刷新功能。
游戏商城列表查看(用户端)
这里主要使用的两个控件就是listView和imageList,以及Panel布局组件(当我点选左侧的游戏时,右侧的游戏详情会进行显示,当然多条件查询也是可以的哈)
管理员账号的登录(游戏管理)
管理员账号登录,右侧显示的侧边栏内容是不一样的,实现了数据的导入导出(可以将Excel中的内容导入到数据库中),然后就是一些crud操作。
在C#中,ListView是一个常用的控件,用于在Windows窗体应用程序中显示数据。它可以以多种方式呈现数据,包括大图标、小图标、列表和详细信息。
在C#中,ImageList是一个用于存储图像集合的类。它提供了一种方便的方式来管理和使用一组图像,通常用于在用户界面控件中显示图像列表。
private void DrawLvGame(DataSet ds)
{
// 先清空,防止计时器一直添加
this.listViewGames.Items.Clear();
this.imageList1.Images.Clear(); //清空图片数组
// 渲染到listView中
if (ds != null && ds.Tables.Count > 0 && ds.Tables[0].Rows.Count > 0)
{
listViewGames.View = View.LargeIcon; //设置listview为大图标模式
listViewGames.LargeImageList = imageList1;// 设置listview的图片数组
listViewGames.Visible = true;
// 开始绘制控件,暂时挂起lv
listViewGames.BeginUpdate();
for (int i = 0; i < ds.Tables[0].Rows.Count; i++)
{
ListViewItem lv = new ListViewItem();
lv.ImageIndex = i;
lv.Text = ds.Tables[0].Rows[i][0].ToString();
// 设置图标
this.imageList1.Images.Add(Image.FromFile(baseImageUrl + ds.Tables[0].Rows[i][1].ToString()));
listViewGames.Items.Add(lv);
}
// 结束绘制
listViewGames.EndUpdate();
}
}
说明:
文件框选择 OpenFileDialog 完成文件上传到本地磁盘功能
private void btnChangeAvatr_Click(object sender, EventArgs e)
{
OpenFileDialog fileDialog = new OpenFileDialog();
fileDialog.Multiselect = true; fileDialog.Title = "请选择文件";
fileDialog.Filter = "所有文件(*jpg*)|*.jpg*"; //设置要选择的文件的类型
if (fileDialog.ShowDialog() == DialogResult.OK)
{
// 获取图片上传的路径
string localFilePath = fileDialog.FileName;
//格式化处理,提取文件名 数据库要存的url
string savePath = localFilePath.Substring(localFilePath.LastIndexOf("\\") + 1);
// 存储到本地目录中 如果本地不存在该图片,那么就上传
if (!File.Exists(baseImageUrl + savePath))
{
File.Copy(localFilePath, baseImageUrl + savePath, false);
}
// 数据库更新操作 传递nickname和新的图片url即可
int flag = UserDataAccess.GetInstance().UpdateUserAvatar(user.Nickname, savePath);
if (flag > 0)
{
MessageBox.Show("更新成功!!\n本地存储图片路径为:" + baseImageUrl + savePath);
RefreshWindow();
}
else
{
MessageBox.Show("修改失败!");
}
}
}
说明:
文件动态替换功能
Bitmap bitmap = new Bitmap(baseImageUrl + user.Avatar);
this.picAvatar.BackgroundImage = bitmap;
说白了就两行代码,PictureBox.BackgroundImage 的值可以是一个 Bitmap对象(Bitmap对象继承自Image对象),而 Bitmap对象可以通过类似File类的方式(通过路径产生)。
因为之前写过一篇类似的博客 ,我就直接贴博客链接了winform .net6 和 framework 的图表控件,为啥项目中不存在chart控件,该如何解决?
因为我这个项目创建的时候,没注意,然后创建的项目是 .net6版本的,所以下面就介绍 ScottPlot 这个图表插件的使用(看文档就基本ok了),scottPlot 官网链接:。
看完之后,就根据自己的需求去选择不同的图表进行配置 https://scottplot.net/cookbook/4.1/,查看它的cookbook就好啦
一个柱状图的demo https://scottplot.net/cookbook/4.1/,感觉着配置都基本不用说,反正按照配置项去获取对应的数据就可以生成一个动态的图表了。
下面贴一张我的SQL图表例子:
SQL工具类,我使用的是一个单例模式
提供一个静态类对象,一个私有构造器,以及一个获取类对象的静态方法。这样就可以避免每次操作数据库去new一个对象了,至始至终都是一个对象在操作。
using GamePlantForm.Dao;
using GamePlantForm.Entity;
using GamePlantForm.Utils;
using Microsoft.VisualBasic.ApplicationServices;
using System;
using System.Collections.Generic;
using System.Data;
using System.Data.SqlClient;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GamePlantForm.DataAccess
{
public class GameDataAccess
{
// 使用单例模式
private static GameDataAccess instance;
private GameDataAccess() { }
public static GameDataAccess GetInstance()
{
return instance ?? (instance = new GameDataAccess());
}
SqlConnection conn;
SqlCommand comm;
SqlDataAdapter adapter;
///
/// 数据库资源释放
///
private void Dispose()
{
if (adapter != null)
{
adapter.Dispose();
adapter = null;
}
if (comm != null)
{
comm.Dispose();
comm = null;
}
if (conn != null)
{
conn.Close();
conn.Dispose();
conn = null;
}
}
///
/// 数据库链接
///
private bool DBConnection()
{
//
string connStr = "Data Source=.\\SQLEXPRESS;database=game_plantform;uid=sa;pwd=123456";
if (conn == null)
{
conn = new SqlConnection(connStr);
}
try
{
conn.Open();
return true;
}
catch (Exception ex)
{
return false;
}
}
}
}
这个的话,重点在于自己找到对应的API接口文档,然后发送请求,用几个实体类对接一些想要的数据即可。我这里只放一下自己写的发送请求的代码。
tips:注意,一定使用自己申请的密钥哇
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Http;
using System.Threading.Tasks;
using GamePlantForm.Entity;
namespace GamePlantForm.Utils
{
// 自定义天气接口工具类
internal class WeatherRobin
{
private readonly HttpClient _httpClient;
public WeatherRobin()
{
_httpClient = new HttpClient();
}
// 150200
public async void GetWeatherAsync(string cityName,Label labprovince,Label labcity, Label labadcode, Label labweather,
Label labtemperature, Label labwinddirection, Label labwindpower, Label labhumidity, Label labreporttime)
{
var response = await _httpClient.GetAsync("https://restapi.amap.com/v3/weather/weatherInfo?city="+cityName+"&key=自己的天气密钥");
var content = await response.Content.ReadAsStringAsync();
// 1. 将获取到的json转换为数组
RootObject obj = Newtonsoft.Json.JsonConvert.DeserializeObject (content);
// 2. 将获取到的数据,填充到传递过来的实体类对象中
labprovince.Text += ":"+ obj.lives[0].province;
labcity.Text += ":" + obj.lives[0].city;
labadcode.Text += ":" + obj.lives[0].adcode;
labweather.Text += ":" + obj.lives[0].weather;
labtemperature.Text += ":" + obj.lives[0].temperature+"℃";
labwinddirection.Text += ":" + obj.lives[0].winddirection;
labwindpower.Text += ":" + obj.lives[0].windpower+"级";
labhumidity.Text += ":" + obj.lives[0].humidity;
labreporttime.Text += ":" + obj.lives[0].reporttime;
}
}
}
ER图之间的关系,有点偷懒了,不想画啦QAQ,这个SQL资源需要的可以找我拿
完整代码,可以私信找我发,也可以通过这篇文章的绑定资源去下载。