本项目已经开源,项目地址:https://github.com/GinSmile/PopDiary
本应用程序是使用c#和xaml技术开发的windows store application,满足微软应用商店审核条件,界面美观简洁,操作简单,可以满足一般用户对日记本的要求。
开发环境
操作系统:Windows 8
开发工具:Visual Studio 2012
一、功能设计
本应用程序的功能图如下:
二、应用结构
文档结构图如下:
其中,
- MainPage.xaml是登陆界面,程序从splashscreen直接跳转到这一个界面上。
- Index.xaml是目录页面,显示所有日记目录。
- DiaryDetail.xaml是编辑界面可以编辑日记。
- UserSetting.xaml是修改密码的页面。
- About.xaml是关于界面
三、各功能模块设计
3.1 登陆模块
本模块对应工程文件中的MainPage.xaml界面文件和MainPage.xaml.cs文件。
界面核心代码如下:
<Grid >
<Grid.Background>
<LinearGradientBrush EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="Black" Offset="0.004"/>
<GradientStop Color="#FF0BADF9" Offset="0.746"/>
</LinearGradientBrush>
</Grid.Background>
<Grid.RowDefinitions>
<RowDefinition Height="140"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Margin="-220,-117,-30,127" Grid.RowSpan="2" HorizontalAlignment="Center" VerticalAlignment="Center" Width="1616">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Button x:Name="go" AutomationProperties.Name="" Grid.Column="1" HorizontalAlignment="Left" Margin="1120,372,0,0" VerticalAlignment="Top" Style="{StaticResource NextAppBarButtonStyle}" Click="check_button" Height="66" Width="91"/>
<PasswordBox x:Name="thePassBox" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Center" Width="265" Margin="850,389,501,336" Height="33" Opacity="0.9" IsPasswordRevealButtonEnabled="True"/>
<Image x:Name="icon" Grid.ColumnSpan="2" Height="218" Margin="0,327,802,0" VerticalAlignment="Top" Source="Assets/account.png" HorizontalAlignment="Right" Width="218" Opacity="0.88"/>
<TextBlock x:Name="tips" Grid.Column="1" HorizontalAlignment="Left" Margin="850,444,0,0" TextWrapping="Wrap" Text="tips" VerticalAlignment="Top" Height="23" Width="152" FontSize="11"/>
<TextBlock Grid.Column="1" HorizontalAlignment="Left" Margin="850,327,0,0" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="33" Width="247" Height="57">
<Run Text="Password"/>
<LineBreak/>
<Run/>
</TextBlock>
</Grid> </Grid>
效果图如下:
核心逻辑代码:
MainPage.xaml.cs |
如果点击了箭头按钮之后就会检验密码是否正确,若正确,则进入日记目录界面,否则更改tips的内容。本段代码用到了Windows.Storage.ApplicationDataContainer类来完成数据的永久存储。当然也可以完成密码修改,具体代码见本文其它部分。 |
public sealed partial class MainPage : Page
{
Windows.Storage.ApplicationDataContainer localSettings;
public string currentPassword;
public MainPage()
{
this.InitializeComponent();
localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
Object value = localSettings.Values["passwordData"];
if (value == null)
{
currentPassword = "12345";
tips.Text = "原始密码为" + currentPassword;
localSettings.Values["passwordData"] = "12345";
}
else
{
tips.Text = "请输入密码";
currentPassword = localSettings.Values["passwordData"].ToString();
}
}
private void check_button(object sender, RoutedEventArgs e)
{
if (thePassBox.Password == currentPassword)
{
tips.Text = "密码正确";
Frame.Navigate(typeof(Index));
}
else
{
tips.Text = "Wrong password, please input again.";
}
}
private void userSetting_Click(object sender, RoutedEventArgs e)
{
this.Frame.Navigate(typeof(UserSetting));
}
private void about_Click(object sender, RoutedEventArgs e)
{
this.Frame.Navigate(typeof(About));
}
}
3.2 目录模块
本模块对应工程文件中的MainPage.xaml界面文件和MainPage.xaml.cs文件。
界面核心代码如下:
MainPage.xaml |
本模块的界面主要是一个GridView,里面存放日记的目录,每个item由两部分组成,即两个TextBlok。分别绑定日记信息中的时间Time和内容Content。 |
<Grid Background="{StaticResource GridImageBrush}" >
<GridView Name="IndexView" ScrollViewer.VerticalScrollBarVisibility="Auto" IsItemClickEnabled="True" SelectionMode="Single" Height="554" Margin="120,163,0,0" VerticalAlignment="Top" ItemClick="Index_ItemClick" HorizontalAlignment="Left" Width="1246" SelectionChanged="select">
<GridView.ItemTemplate>
<DataTemplate> <StackPanel Name="myItem" Orientation="Vertical" Height="250" Width="200" Background="#FF00B7EF">
<TextBlock Text="{Binding Time}"></TextBlock>
<TextBlock TextWrapping="Wrap" Text="{Binding Content}"></TextBlock>
</StackPanel>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
<Image HorizontalAlignment="Left" Height="91" Width="423" Source="Assets/splshScreenNoBar.png" Margin="120,57,0,620"/>
<Button x:Name="AddDiary" HorizontalAlignment="Left" Margin="1109,64,0,0" VerticalAlignment="Top" Click="AddNewDiary" Style="{StaticResource AddAppBarButtonStyle}"/>
</Grid>
核心逻辑代码:
MyDiary.cs |
MyDiary类定义的代码,实现了INotifyPropertyChanged接口,定义了两个string类型的变量,在绑定之后可将对MyDiary对象的更改反映到界面上。 |
public class MyDiary : INotifyPropertyChanged
{
private string _time;
private string _content;
public string Time
{
get
{
return _time;
}
set
{
_time = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Time"));
}
}
}
public string Content
{
get
{
return _content;
}
set
{
_content = value;
if (PropertyChanged != null)
{
PropertyChanged(this, new PropertyChangedEventArgs("Content"));
}
}
}
public override string ToString()
{
return "Time:" + Time + "\nContent:" + Content;
}
public event PropertyChangedEventHandler PropertyChanged;
}
初始化(Index.xaml.cs) |
重写OnNavigatedTo函数,当程序导航到本页面的时候触发。在此程序中,实现了检验是否第一次访问该应用程序(使用localSettings.Values["first"]这个键值对)。当确定是第一次访问的时候,添加进去一篇初始的日记来介绍本程序,否则加载用户之前的日记信息。 |
Static ObservableCollection<MyDiary> myIndex;
static Windows.Storage.ApplicationDataContainer localSettings = Windows.Storage.ApplicationData.Current.LocalSettings;
static Windows.Storage.ApplicationDataContainer container = localSettings.CreateContainer("diaryContainer", Windows.Storage.ApplicationDataCreateDisposition.Always);
protected override void OnNavigatedTo(NavigationEventArgs e)
{
if (e.NavigationMode == NavigationMode.New)
{
// Composite setting
if (localSettings.Values["first"] == null)
{
// 第一次进入,程序里面没有数据;
myIndex = new ObservableCollection<MyDiary>();
myIndex.Add(new MyDiary { Time = getNow(), Content = "欢迎使用Pop Diary(泡泡日记本).您可以使用它来记录你的每一天。" });
}
else {
if (localSettings.Containers.ContainsKey("diaryContainer"))
{
myIndex = new ObservableCollection<MyDiary>();
int length = int.Parse(localSettings.Containers["diaryContainer"].Values["length"].ToString());
for (int i = 0; i < length; i++ )
myIndex.Add(new MyDiary { Time = localSettings.Containers["diaryContainer"].Values["time" + i].ToString(),
Content = localSettings.Containers["diaryContainer"].Values["content" + i].ToString() });
}
}
IndexView.ItemsSource = myIndex;
}
}
存储数据功能(Index.xaml.cs) |
storeData()函数,把日记相关数据存储到localSettings中。 |
static public void storeData() {
if (myIndex != null)
{
int length = myIndex.Count;
localSettings.Containers["diaryContainer"].Values["length"] = length;
for (int i = 0; i < length; i++)
{
localSettings.Containers["diaryContainer"].Values["time" + i] = myIndex.ElementAt(i).Time;
localSettings.Containers["diaryContainer"].Values["content" + i] = myIndex.ElementAt(i).Content;
}
localSettings.Values["first"] = "false";
}
}
3.3添加日记
添加日记功能(Index.xaml.cs) |
AddNewDiary()函数,用来添加日记用的,点击添加日记按钮后触发,该函数传递一个Diary类型的对象给DiaryDetail页面。 |
private void AddNewDiary(object sender, RoutedEventArgs e)
{
string now = getNow();
MyDiary diary = new MyDiary { Time = now, Content = " " };
myIndex.Insert(0, diary);
storeData();
this.Frame.Navigate(typeof(DiaryDetail), diary);
}
点击某个日记导航到编辑页面(Index.xaml.cs) |
点击GridView中的任何一个项目,都会触发这个事件,并且会传递一个参数,该参数为Object类型的对象,可以在DiaryDetail页面中转化为diary = (MyDiary)navigationParameter; |
private void Index_ItemClick(object sender, ItemClickEventArgs e)
{
this.Frame.Navigate(typeof(DiaryDetail), e.ClickedItem);
}
3.4 删除模块
删除功能(Index.xaml.cs) |
当选中一个日记的时候会触发select函数,从而改变indexNum的值,这个值代表这个日记的标号,程序根据这个标号来对日记进行处理。 |
int indexNum = 0;
private void select(object sender, SelectionChangedEventArgs e)
{
indexNum = IndexView.SelectedIndex;
......
}
private void remove_Click(object sender, RoutedEventArgs e)
{
myIndex.RemoveAt(indexNum);
remove.Visibility = Windows.UI.Xaml.Visibility.Visible;
removeAll.Visibility = Windows.UI.Xaml.Visibility.Visible;
storeData();
}
private async void removeAll_Click(object sender, RoutedEventArgs e)
{
MessageDialog md = new MessageDialog("确定删除所有日记?");
md.Commands.Add(new UICommand("确定", command =>
{
myIndex.Clear();
}));
md.Commands.Add(new UICommand("取消", command =>
{
//do nothing
}));
await md.ShowAsync();
storeData();
}
3.5导出模块
本模块对应工程文件中的Index.xaml.cs文件,图标按钮在Appbar中。
导出功能(Index.xaml.cs) |
点击导出为txt文本按钮,就会触发这个事件,把应用程序存储中的所有数据都存储一个txt文件中。 |
private async void export_Click(object sender, RoutedEventArgs e)
{
if(this.EnsureUnsnapped()){
FileSavePicker savePicker = new FileSavePicker();
savePicker.SuggestedStartLocation = PickerLocationId.DocumentsLibrary;
savePicker.FileTypeChoices.Add("Plain Text", new List<string>() { ".txt" });
savePicker.SuggestedFileName = "MyDiary";
StorageFile file = await savePicker.PickSaveFileAsync();
if (file != null)
{
CachedFileManager.DeferUpdates(file);
string theAllDiary = "";
foreach (MyDiary s in myIndex) {
theAllDiary += s.Time + Environment.NewLine + s.Content +
Environment.NewLine + Environment.NewLine;
}
await FileIO.WriteTextAsync(file, theAllDiary);
FileUpdateStatus status =
await CachedFileManager.CompleteUpdatesAsync(file);
if (status == FileUpdateStatus.Complete)
{
MessageDialog md = new MessageDialog("保存成功");
await md.ShowAsync();
}
else
{
MessageDialog md = new MessageDialog("保存未成功");
await md.ShowAsync();
}
}
}
}
保存之后打开该文件,MyDiary.,xt文件中内容如下: