基于WPF+Sqlite开发抽奖软件【内附源码】

  • 基于WPF+Sqlite开发抽奖软件【内附源码】已关闭评论
  • 57 次浏览
  • A+
所属分类:.NET技术
摘要

在很早之前,就想过开发一款抽奖软件,却一直没有实际去做,最近经过一段时间的准备,终于开发出了一款基于WPF+Sqlite版的抽奖软件,包括客户端和管理端。本项目主要是为了熟悉WPF开发流程,仅供学习分享使用,如有不足之处,还请指正。

在很早之前,就想过开发一款抽奖软件,却一直没有实际去做,最近经过一段时间的准备,终于开发出了一款基于WPF+Sqlite版的抽奖软件,包括客户端和管理端。本项目主要是为了熟悉WPF开发流程,仅供学习分享使用,如有不足之处,还请指正。

 

涉及知识点

 

抽奖软件是包括客户端和管理端,在抽奖软件开发过程中,主要用到了如下知识点:

  • 开发工具:Visual Studion 2022
  • 开发框架:.NET6.0 + WPF
  • MVVM框架:CommunityToolkit.Mvvm 8.2.2
  • 数据库:Sqlite
  • ORM框架:SqlSugarCore 5.1.4.154
  • 数据库客户端:SQLiteStudio 3.4.4

 

数据表设计

 

根据抽奖软件的功能进行拆解,主要包括:Gift(礼品表),Lucky(奖品表),User(抽奖用户表),Winner(中奖表),各个表详细创建语句如下所示:

Gift(礼品表),主要包括礼品名称,图片路径等,如下所示:

CREATE TABLE gift (     Id       INTEGER       PRIMARY KEY AUTOINCREMENT,     Name     VARCHAR (255),     ImageUrl VARCHAR (255)  );

Lucky(奖品表),主要包括,奖品名称,数量,对应礼品ID,奖品等级(如:一等奖,二等奖),奖品类型,奖品排序(抽奖顺序),如下所示:

CREATE TABLE lucky (     Id         INTEGER      PRIMARY KEY AUTOINCREMENT,     Name       VARCHAR (50),     Count      INTEGER,     GiftId     INTEGER,     Level      INTEGER,     LuckyType  VARCHAR (50),     LuckyOrder INTEGER );

 User(抽奖用户表),参与抽奖的用户,主要用户的名称,如下所示:

CREATE TABLE user (     Id   INTEGER      PRIMARY KEY AUTOINCREMENT,     Name VARCHAR (50)  );

 Winner(中奖表),主要包括中奖用户ID,奖品ID,中奖时间等。如下所示:

CREATE TABLE winner (     Id         INTEGER  PRIMARY KEY AUTOINCREMENT,     userid     INTEGER,     luckyid    INTEGER,     winnertime DATETIME );

 

功能设计

 

抽奖软件主要包括客户端,和管理端,主要功能如下:

  • 客户端,主要用于抽奖,包括首页,抽奖页面【Enter键开始和停止抽奖,Next键切换奖项】,结束语页面。
  • 管理端,主要用于管理数据信息,包括用户管理,礼品管理,奖品管理,中奖管理等功能,主要是对各个数据表的增删改查。

 

核心源码

 

本实例项目虽然比较小,但作为一个完整的项目,为了层次清晰及便于维护,采用MVVM开发模式,UI和业务逻辑分层处理,并单独封装DAL层。

 

1. 抽奖页面源码

 

整个项目最核心的就是抽奖页面,UI层代码如下所示:

<UserControl x:Class="EasyLucky.Views.Lucky"              xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"              xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"              xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"               xmlns:d="http://schemas.microsoft.com/expression/blend/2008"               xmlns:i="http://schemas.microsoft.com/xaml/behaviors"              xmlns:local="clr-namespace:EasyLucky.Views"              mc:Ignorable="d"               d:DesignHeight="450" d:DesignWidth="1000">     <i:Interaction.Triggers>         <i:EventTrigger EventName="Loaded">             <i:InvokeCommandAction Command="{Binding LoadedCommand}" PassEventArgsToCommand="True" ></i:InvokeCommandAction>         </i:EventTrigger>     </i:Interaction.Triggers>     <Grid>         <i:Interaction.Triggers>             <i:EventTrigger EventName="MouseDown">                 <i:InvokeCommandAction Command="{Binding MouseDownCommand}" PassEventArgsToCommand="True" ></i:InvokeCommandAction>             </i:EventTrigger>         </i:Interaction.Triggers>         <Grid.ColumnDefinitions>             <ColumnDefinition></ColumnDefinition>             <ColumnDefinition></ColumnDefinition>         </Grid.ColumnDefinitions>         <Grid.RowDefinitions>             <RowDefinition Height="Auto"></RowDefinition>             <RowDefinition Height="*"></RowDefinition>             <RowDefinition Height="Auto"></RowDefinition>         </Grid.RowDefinitions>         <Border Grid.ColumnSpan="2" Grid.RowSpan="3">             <Image Source="/imgs/BG_12.jpg"  Stretch="Fill"></Image>         </Border>         <StackPanel Orientation="Horizontal" VerticalAlignment="Top" Margin="0 40 0 0" Grid.Column="0" Grid.ColumnSpan="2" HorizontalAlignment="Center">             <TextBlock Text="正在抽取的是 " FontSize="40" Foreground="White" VerticalAlignment="Center"></TextBlock>             <TextBlock Text="{Binding DataM.CurLucky.Lucky.Level}" FontSize="60" Foreground="Gold" FontWeight="DemiBold"></TextBlock>             <TextBlock Text=" 等奖,共 " FontSize="40" Foreground="White" VerticalAlignment="Center"></TextBlock>             <TextBlock Text="{Binding DataM.CurLucky.Lucky.Count}" FontSize="60" Foreground="Gold" FontWeight="DemiBold"></TextBlock>             <TextBlock Text=" 名" FontSize="40" Foreground="White" VerticalAlignment="Center"></TextBlock>         </StackPanel>         <ItemsControl Grid.Row="1" Grid.Column="0" ItemsSource="{Binding DataM.CurUsers}" Grid.ColumnSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" VerticalContentAlignment="Center">             <ItemsControl.ItemsPanel>                 <ItemsPanelTemplate>                     <UniformGrid Columns="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.DataM.Column}" Rows="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type UserControl}},Path=DataContext.DataM.Row}" >                     </UniformGrid>                 </ItemsPanelTemplate>             </ItemsControl.ItemsPanel>             <ItemsControl.ItemTemplate>                 <DataTemplate>                     <TextBlock Text="{Binding Name}" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="40" FontWeight="DemiBold" Foreground="White" Margin="30"></TextBlock>                 </DataTemplate>             </ItemsControl.ItemTemplate>         </ItemsControl>                  <StackPanel Margin="100 0 0 10" Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" Orientation="Horizontal" HorizontalAlignment="Center">             <Grid>                 <Grid.ColumnDefinitions>                     <ColumnDefinition></ColumnDefinition>                     <ColumnDefinition></ColumnDefinition>                 </Grid.ColumnDefinitions>                 <Grid.RowDefinitions>                     <RowDefinition></RowDefinition>                     <RowDefinition></RowDefinition>                 </Grid.RowDefinitions>                 <StackPanel Orientation="Horizontal" Grid.Row="0" Grid.Column="0">                     <TextBlock Text="{Binding DataM.CurLucky.Lucky.Level}" FontSize="40" Foreground="Gold" FontWeight="DemiBold" VerticalAlignment="Center"></TextBlock>                     <TextBlock Text=" 等奖奖品" FontSize="40" Foreground="White" VerticalAlignment="Center"></TextBlock>                 </StackPanel>                 <TextBlock Text="{Binding DataM.CurLucky.Gift.Name}" FontSize="40" Grid.Row="1" Grid.Column="0" Foreground="Gold" FontWeight="DemiBold" VerticalAlignment="Center" HorizontalAlignment="Center"></TextBlock>                 <Image Margin="20 0 0 0" Source="{Binding DataM.CurLucky.Gift.ImageSource}" Stretch="Fill" Grid.Row="0" Grid.Column="1" Grid.RowSpan="2" Width="200" Height="150"></Image>             </Grid>         </StackPanel>         <TextBlock x:Name="btn" Grid.Column="1" Grid.Row="2" Background="Transparent" Width="10" Height="10" Focusable="True" HorizontalAlignment="Right" VerticalAlignment="Bottom">             <i:Interaction.Triggers>                 <i:EventTrigger EventName="KeyDown">                     <i:InvokeCommandAction Command="{Binding KeyDownCommand}" PassEventArgsToCommand="True"></i:InvokeCommandAction>                 </i:EventTrigger>             </i:Interaction.Triggers>         </TextBlock>     </Grid> </UserControl>

 

2. 业务逻辑源码

 

业务逻辑代码在ViewModel 中,如下所示:

 

开始抽奖,通过Enter键触发:

private void Start() { 	cts = new CancellationTokenSource(); 	token = cts.Token; 	task = Task.Run(() => 	{ 		var luckyCount = this.DataM.CurLucky.Lucky.Count; 		var userCount = this.DataM.Users.Count; 		var random = new Random(DateTime.Now.Second); 		var rnd = random.Next(0,userCount); 		int index = rnd; 		if(index+luckyCount > userCount) 		{ 			index = userCount - luckyCount; 		} 		 		while (!token.IsCancellationRequested) 		{ 			var users=new List<User>(); 			if(index+luckyCount > userCount) 			{ 				//读到最后再循环读取 				for(int i = index; i < userCount; i++) 				{ 					users.Add(this.DataM.Users[i]); 				} 				for(int i = 0; i < luckyCount - (userCount - index); i++) 				{ 					users.Add(this.DataM.Users[i]); 				} 				index = luckyCount - (userCount - index); 			} 			else 			{ 				//顺序读取 				for (int i = index; i < index+luckyCount; i++) 				{ 					users.Add(this.DataM.Users[i]); 				} 				index=index+luckyCount; 			} 			Application.Current.Dispatcher.Invoke(new Action(() => 			{ 				this.DataM.CurUsers = new ObservableCollection<User>(users); 			})); 			Thread.Sleep(100); 		} 	},token); 	this.DataM.State = 1; }

 

停止抽奖 ,并保存中奖结果:

private void Stop() { 	cts.Cancel(); 	//获取当前获奖名单 	var users = this.DataM.CurUsers.ToList(); 	var lucky = this.DataM.CurLucky.Lucky; 	if (winnerDal == null) 	{ 		winnerDal = new WinnerDal(); 	} 	foreach(var user in users) 	{ 		var entity = new WinnerEntity() 		{ 			UserId = user.Id, 			LuckyId = lucky.Id, 			WinnerTime = DateTime.Now, 		}; 		int id= this.winnerDal.AddWinner(entity); 		if(id <1) 		{ 			MessageBox.Show("添加失败"); 			break; 		} 	} 	// 	for(int i=0; i<users.Count; i++) 	{ 		var user = users[i]; 		this.DataM.Users.Remove(user);//从列表中移除中奖名单 	} 	this.DataM.State=0; }

 

下一个奖项,按照奖项顺序选择下一个奖项,通过Next键触发,如下所示:

private void Next() { 	int order = this.DataM.CurLucky.Lucky.LuckyOrder; 	var next = this.DataM.Luckys.FirstOrDefault(item => item.LuckyOrder > order); 	if (next != null) 	{ 		this.DataM.CurLucky.Lucky = next; 		var giftId = this.DataM.CurLucky.Lucky.GiftId; 		this.DataM.CurLucky.Gift = this.DataM.Gifts.FirstOrDefault(item => item.Id == giftId); 		if (next.Count > 4) 		{ 			this.DataM.Row = 2; 			this.DataM.Column = (int)Math.Ceiling(next.Count * 1.0d / 2); 		} 		this.DataM.State = 0; 		this.DataM.CurUsers.Clear(); 	} 	else 	{ 		WeakReferenceMessenger.Default.Send(new StateChangedMessage(2)); 	} }

 

效果演示

 

抽奖软件实例演示,客户端主要包括首页,抽奖页,结束页,如下所示:

 

首页实例

基于WPF+Sqlite开发抽奖软件【内附源码】

 

抽奖页面

基于WPF+Sqlite开发抽奖软件【内附源码】

 

结束语页面

基于WPF+Sqlite开发抽奖软件【内附源码】

 

管理端主要是对数据的管理,包括礼品管理,用户管理,奖项管理,中奖管理,属于常规的数据管理页面,如下所示:

基于WPF+Sqlite开发抽奖软件【内附源码】

 

源码下载

 

1. gitee下载

 

源码已上传至gitee,用户可通过gitee链接进行下载,如下所示:
项目链接:https://gitee.com/ahsiang/easy-lucky

基于WPF+Sqlite开发抽奖软件【内附源码】

 

2. 关键字下载

 

关注个人公众号,回复关键字Lucky即可,如下所示:

基于WPF+Sqlite开发抽奖软件【内附源码】

以上就是基于WPF+Sqlite开发抽奖软件实例的全部内容,希望可以抛砖引玉,一起学习,共同进步。