Compact Framework电影收藏管理器






3.23/5 (26投票s)
一个使用 Compact Framework 和 SQL Server CE 的示例。
引言
本文旨在说明使用 Compact Framework、SQL Server CE 和 Windows Forms 创建一个相对简单的“数据库”应用程序所需的步骤。
本应用程序将向您介绍如何从 Compact Framework 应用程序创建、填充和查询 SQL Server CE 数据库。
我的一位朋友拥有大量的 DVD 和 VHS 电影收藏,他已 painstaking 地整理并编号。当我开始寻找开发想法时,他提到了拥有一个可以保存这些信息并能够搜索特定类型电影的应用程序将多么有用。
这是我的第一次投稿,请多指教。
背景
我的背景主要集中在 MFC Windows 编程,但最近我也参与了一些 ASP.NET 编程。这激发了我对 C# 和 Windows Forms 的兴趣,而且我一直是 Pocket PC/Windows Mobile 设备的大粉丝。因此,我接受了使用 C# 和 Compact Framework 创建一个手持应用程序的挑战。最初,我曾打算使用 Access 作为数据库,因为我对它很熟悉,但发现它不支持。我还研究了使用 XML 进行存储,但事实证明太笨拙了。
使用代码
代码分为两个类,每个类对应应用程序中的一个窗体。主窗体包含一个带有两个面板的选项卡控件,以及一个 ListView 控件。ListView 支持“上下文菜单”,其中包含两个菜单选项。一个菜单选项支持删除选定的记录,另一个则弹出记录详细信息窗体。
收藏选项卡显示了收藏中电影的评分分类,以及一个创建新记录的按钮。另一个选项卡“筛选”支持按各种属性筛选收藏。
详细信息窗体提供了用于创建和修改电影记录的控件。它通过获取控件的值并将其应用于数据库来简单地添加或更新记录。
应用程序中最有趣的部分可能是它如何使用 SQL Server CE。
创建数据库
代码创建一个名为 MovieManager.sdf 的新的 SQL Server CE 文件。
private SqlCeEngine m_cEngine = null;
private SqlCeConnection m_cConn = null;
public MovieManagerForm()
{
//
// Required for Windows Form Designer support
//
InitializeComponent();
// Instantiate a SqlCeEngine object
m_cEngine = new SqlCeEngine(
"Data Source = \\My Documents\\MovieManager.sdf");
// Check to see if the DB is already there, if not call a func to
// create it and it's tables
bool bCreated = false;
if ( !File.Exists("\\My Documents\\MovieManager.sdf") )
{
bCreated = true;
m_cEngine.CreateDatabase();
}
m_cConn = new SqlCeConnection(
"Data Source = \\My Documents\\MovieManager.sdf");
m_cConn.Open();
if ( bCreated )
DoInitialDatabaseSetup();
}
private void DoInitialDatabaseSetup()
{
// Instantiate a SqlCeCommand object
SqlCeCommand sqlCreateTable = m_cConn.CreateCommand();
// Create the MOVIE_MNGR_TABLE
sqlCreateTable.CommandText =
"CREATE TABLE MOVIE_MNGR_TABLE(MovieID int IDENTITY(0,1) " +
"PRIMARY KEY, MovieNmbr ntext, MovieTitle ntext, " +
"MovieRating int, MovieFormat int, MovieType int, " +
"Animated bit, MovieNotes ntext)";
sqlCreateTable.ExecuteNonQuery();
}
基本上,引擎被初始化,如果 SDF 文件不存在,它会被创建,然后建立到数据库的连接,最后,如果文件被创建,则通过 SQL 命令构建表。
查询数据库并加载列表
private void LoadList(string szSQL)
{
// Clear out anything that might already be in the list
CollectionList.Items.Clear();
// save off the SQL Statement
m_szCurrFilter = szSQL;
// Throw Movies into the list
SqlCeCommand sqlLoadEvents = m_cConn.CreateCommand();
sqlLoadEvents.CommandText = szSQL;
SqlCeDataReader rReader = sqlLoadEvents.ExecuteReader();
// roll through the reader and put items into the list
while ( rReader.Read() )
{
ListViewItem lvItem = new ListViewItem(
rReader.GetValue(rReader.GetOrdinal(
"MovieNmbr")).ToString() ); //Nmbr
// Note: Since a "tag" is not supported by the
// compact framework, we'll use the "ImageIndex"
// property to hold the movie ID, this way we can
// find it later when the user clicks
// on a movie
lvItem.ImageIndex = (int)rReader.GetValue(
rReader.GetOrdinal("MovieID"));
lvItem.SubItems.Add( rReader.IsDBNull(rReader.GetOrdinal(
"MovieTitle")) ? "" : rReader.GetValue(
rReader.GetOrdinal("MovieTitle")).ToString()); // Title
lvItem.SubItems.Add(GetRatingFromNumber((int)rReader.GetValue(
rReader.GetOrdinal("MovieRating")) )); // Rating
CollectionList.Items.Add( lvItem );
}
}
此方法查询数据库,并通过 SqlCeReader
对象将行添加到 ListView。我决定传递 SQL SELECT 语句,因为这样我就可以重用此方法来支持用户进行筛选。此方法将提供的筛选条件保存到成员变量中,以便以后重用。
修改数据库
// Adding a new Movie Record
SqlCeCommand sqlCommand = m_cConn.CreateCommand();
sqlCommand.CommandText = "INSERT INTO MOVIE_MNGR_TABLE (MovieNmbr,"+
"MovieTitle, MovieRating, MovieFormat, MovieType, Animated, "+
"MovieNotes) VALUES (?, ?, ?, ?, ?, ?, ?)";
sqlCommand.Parameters.Add(new SqlCeParameter("MovieNmbr",
SqlDbType.NText)).Value = NumberText.Text;
sqlCommand.Parameters.Add(new SqlCeParameter("MovieTitle",
SqlDbType.NText)).Value = TitleText.Text;
sqlCommand.Parameters.Add(new SqlCeParameter("MovieRating",
SqlDbType.Int)).Value = RatingCombo.SelectedIndex+1;
sqlCommand.Parameters.Add(new SqlCeParameter("MovieFormat",
SqlDbType.Int)).Value = FormatCombo.SelectedIndex+1;
sqlCommand.Parameters.Add(new SqlCeParameter("MovieType",
SqlDbType.Int)).Value = TypeCombo.SelectedIndex+1;
sqlCommand.Parameters.Add(new SqlCeParameter("Animated",
SqlDbType.Bit)).Value = CheckState.Checked ==
AnimatedCheckBox.CheckState ? true : false;
sqlCommand.Parameters.Add(new SqlCeParameter("MovieNotes",
SqlDbType.NText)).Value = NotesText.Text;
sqlCommand.ExecuteNonQuery();
添加记录使用传统的 INSERT 语句。我决定使用 SqlCeParameter
对象来防止包含撇号的数据。一切都很直接,但如果 SQL 语句中的任何内容不正确或位置不对,都会抛出异常。我决定将评分和类型等值在数据库中保存为数字而不是字符串,并决定为筛选保留零。
// Updating an existing Movie Record
SqlCeCommand sqlCommand = m_cConn.CreateCommand();
sqlCommand.CommandText =
"UPDATE MOVIE_MNGR_TABLE set MovieNmbr = ?, " +
"MovieTitle = ?, MovieRating = ?, MovieFormat = ?,"+
" MovieType = ?, Animated = ?, MovieNotes = ? WHERE "+
"MovieID = " + m_nMovieID.ToString();;
sqlCommand.Parameters.Add(new SqlCeParameter("MovieNmbr",
SqlDbType.NText)).Value = NumberText.Text;
sqlCommand.Parameters.Add(new SqlCeParameter("MovieTitle",
SqlDbType.NText)).Value = TitleText.Text;
sqlCommand.Parameters.Add(new SqlCeParameter("MovieRating",
SqlDbType.Int)).Value = RatingCombo.SelectedIndex+1;
sqlCommand.Parameters.Add(new SqlCeParameter("MovieFormat",
SqlDbType.Int)).Value = FormatCombo.SelectedIndex+1;
sqlCommand.Parameters.Add(new SqlCeParameter("MovieType",
SqlDbType.Int)).Value = TypeCombo.SelectedIndex+1;
sqlCommand.Parameters.Add(new SqlCeParameter("Animated",
SqlDbType.Bit)).Value = CheckState.Checked ==
AnimatedCheckBox.CheckState ? true : false;
sqlCommand.Parameters.Add(new SqlCeParameter("MovieNotes",
SqlDbType.NText)).Value = NotesText.Text;
sqlCommand.ExecuteNonQuery();
更新几乎与插入相同。
关注点
SQL Server CE
我在没有安装 Activesync 的机器上进行了所有开发,使用模拟器进行初步测试,然后将可执行文件复制到 SD 卡并在我的 Dell Axim 上运行。模拟器运行良好,因为 Studio 自动安装了必要的 SQL CE 组件,但在 Axim 上启动它稍微困难一些。最终,我找到了代表 SQL Server CE 的两个 CAB 文件,并在实际的掌上设备上运行了它们。您的环境应该有您需要的 CAB 文件。最终,我发现我需要 'sqlce.dev.ppc3.arm.CAB' 和 'sqlce.ppc3.arm.CAB'。
SQLCE 查询应用程序在模拟器和掌上设备上运行 ad-hoc 查询以进行调试和测试非常有用,但您必须记住在启动应用程序之前“关闭”数据库。
注意:要使用 SQL Server CE,请添加一个 'using System.Data.SqlServerCe;
' 语句,以及对 System.Data.SqlServerCe
的引用。
Windows Forms 和 Compact Framework
虽然 Compact Framework 使使用 Windows Forms 变得相当轻松,但偶尔我也会遇到一些框架不支持的陷阱。例如,在我进行 MFC 编程时,我喜欢使用列表控件行的“Item Data”来保存该行的唯一 ID,以便于删除等操作。我发现 Framework 不支持 ListView 控件中的 'Tag' 属性,因此作为一种变通方法,我使用了 ImageIndex
属性。如果将来我想添加图像列表,我将不得不寻找其他方法。
我喜欢 Windows Forms 能够轻松更改背景颜色、字体和其他视觉元素,但不幸的是,它并非在框架的所有控件中都支持。
历史
- 2004 年 5 月 14 日 - 初次提交