基於WPF+Sqlite開發抽獎軟體【內附源碼】

来源:https://www.cnblogs.com/hsiang/p/18205190
-Advertisement-
Play Games

在很早之前,就想過開發一款抽獎軟體,卻一直沒有實際去做,最近經過一段時間的準備,終於開發出了一款基於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));
	}
}

 

效果演示

 

抽獎軟體實例演示,客戶端主要包括首頁,抽獎頁,結束頁,如下所示:

 

首頁實例

 

抽獎頁面

 

結束語頁面

 

管理端主要是對數據的管理,包括禮品管理,用戶管理,獎項管理,中獎管理,屬於常規的數據管理頁面,如下所示:

 

源碼下載

 

1. gitee下載

 

源碼已上傳至gitee,用戶可通過gitee鏈接進行下載,如下所示:
項目鏈接:https://gitee.com/ahsiang/easy-lucky

 

2. 關鍵字下載

 

關註個人公眾號,回覆關鍵字Lucky即可,如下所示:

以上就是基於WPF+Sqlite開發抽獎軟體實例的全部內容,希望可以拋磚引玉,一起學習,共同進步。


作者:小六公子
出處:http://www.cnblogs.com/hsiang/
本文版權歸作者和博客園共有,寫文不易,支持原創,歡迎轉載【點贊】,轉載請保留此段聲明,且在文章頁面明顯位置給出原文連接,謝謝。
關註個人公眾號,定時同步更新技術及職場文章


您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 配置 NGINX 和 NGINX Plus 作為 Web 伺服器 設置虛擬伺服器 在 NGINX Plus 配置文件中,必須包含至少一個 server 指令來定義一個虛擬伺服器。 當 NGINX Plus 處理請求時,首先選擇將服務於該請求的虛擬伺服器。 http { server { # 伺服器配 ...
  • title: Django與前端框架協作開發實戰:高效構建現代Web應用 date: 2024/5/22 20:07:47 updated: 2024/5/22 20:07:47 categories: 後端開發 tags: DjangoREST 前端框架 SSR渲染 SPA路由 SEO優化 組件庫 ...
  • 在使用Wrapper構建條件時,經常因為需要構建的條件過多需要寫半個多小時,還容易粗心寫錯欄位,所以就想搞個可以直接自動構建QueryWrapper的工具類。 ...
  • 今天使用Thinkphp5做非同步任務傳遞where參數時遇到一個問題: 有一段如下代碼: $where['jst.supplier'] = ['exp', Db::raw('>0 or jst.is_supplier=1')]; 在使用swoole做非同步任務時需要把where參數傳遞給非同步任務處理, ...
  • 前言 市面上關於認證授權的框架已經比較豐富了,大都是關於單體應用的認證授權,在分散式架構下,使用比較多的方案是--<應用網關>,網關里集中認證,將認證通過的請求再轉發給代理的服務,這種中心化的方式並不適用於微服務,這裡討論另一種方案--<認證中心>,利用jwt去中心化的特性,減輕認證中心的壓力,有理 ...
  • EDP是一套集組織架構,許可權框架【功能許可權,操作許可權,數據訪問許可權,WebApi許可權】,自動化日誌,動態Interface,WebApi管理等基礎功能於一體的,基於.net的企業應用開發框架。通過友好的編碼方式實現數據行、列許可權的管控。 ...
  • 在小公司中,往往沒有一個前後端分離的大型團隊,去各司其職的負責構建web應用程式。面對比較簡單的需求,可能所謂團隊只有一個人,既要開發前端又要開發後端。 如果能有一項技術,能夠前後端通吃,並且具備非常高的開發效率,那就非常適合小公司的小型項目的小型甚至一人團隊來使用了。 aspdotnet就是這樣高 ...
  • 結構體 struct 是一種用戶自定義的值類型,常用於定義一些簡單(輕量)的數據結構。對於一些局部使用的數據結構,優先使用結構體,效率要高很多。 ...
一周排行
    -Advertisement-
    Play Games
  • 一個自定義WPF窗體的解決方案,借鑒了呂毅老師的WPF製作高性能的透明背景的異形視窗一文,併在此基礎上增加了滑鼠穿透的功能。可以使得透明窗體的滑鼠事件穿透到下層,在下層窗體中響應。 ...
  • 在C#中使用RabbitMQ做個簡單的發送郵件小項目 前言 好久沒有做項目了,這次做一個發送郵件的小項目。發郵件是一個比較耗時的操作,之前在我的個人博客裡面回覆評論和友鏈申請是會通過發送郵件來通知對方的,不過當時只是簡單的進行了非同步操作。 那麼這次來使用RabbitMQ去統一發送郵件,我的想法是通過 ...
  • 當你使用Edge等瀏覽器或系統軟體播放媒體時,Windows控制中心就會出現相應的媒體信息以及控制播放的功能,如圖。 SMTC (SystemMediaTransportControls) 是一個Windows App SDK (舊為UWP) 中提供的一個API,用於與系統媒體交互。接入SMTC的好 ...
  • 最近在微軟商店,官方上架了新款Win11風格的WPF版UI框架【WPF Gallery Preview 1.0.0.0】,這款應用引入了前沿的Fluent Design UI設計,為用戶帶來全新的視覺體驗。 ...
  • 1.簡單使用實例 1.1 添加log4net.dll的引用。 在NuGet程式包中搜索log4net並添加,此次我所用版本為2.0.17。如下圖: 1.2 添加配置文件 右鍵項目,添加新建項,搜索選擇應用程式配置文件,命名為log4net.config,步驟如下圖: 1.2.1 log4net.co ...
  • 之前也分享過 Swashbuckle.AspNetCore 的使用,不過版本比較老了,本次演示用的示例版本為 .net core 8.0,從安裝使用開始,到根據命名空間分組顯示,十分的有用 ...
  • 在 Visual Studio 中,至少可以創建三種不同類型的類庫: 類庫(.NET Framework) 類庫(.NET 標準) 類庫 (.NET Core) 雖然第一種是我們多年來一直在使用的,但一直感到困惑的一個主要問題是何時使用 .NET Standard 和 .NET Core 類庫類型。 ...
  • WPF的按鈕提供了Template模板,可以通過修改Template模板中的內容對按鈕的樣式進行自定義。結合資源字典,可以將自定義資源在xaml視窗、自定義控制項或者整個App當中調用 ...
  • 實現了一個支持長短按得按鈕組件,單擊可以觸發Click事件,長按可以觸發LongPressed事件,長按鬆開時觸發LongClick事件。還可以和自定義外觀相結合,實現自定義的按鈕外形。 ...
  • 一、WTM是什麼 WalkingTec.Mvvm框架(簡稱WTM)最早開發與2013年,基於Asp.net MVC3 和 最早的Entity Framework, 當初主要是為瞭解決公司內部開發效率低,代碼風格不統一的問題。2017年9月,將代碼移植到了.Net Core上,併進行了深度優化和重構, ...