PCL Storage (1)
In the sample programs of ListView (1) and (2), new book titles can be added to the book list, so I naturally wanted to build the new function to save the book list.
I found that there are some ways to save data processed in App.
This sample App is composed of two tabbed pages, and processing example of folder and file I/O has been implemented to the pages respectively.
I explain how to build folder and file I/O below.
Get the current folder path, create new folders, check folders already exists, delete folders are implemented in this Folder I/O tabbed page. The results of the processing are displayed in the ListView set at the bottom of the page.
I used Trigger function on some Entry and Button control to enhance their effect.
IFolder, async/await etc. were a little bit confusing, but I finally made the code shown above.
It was somewhat difficult to display folder list. I found that IEnumerator was useful to do it, and could successfully get folder names as text array data and show them in ListView. But I have not deeply understood IEnumerater yet, and I have to study it.
In addition to create and delete files like folder I/O, read file contents and additionally write contents to file were also implemented. In display of file list, added MenuItem context actions, and move to the EditFile page explained later and delete file are available in it.
By the way, text.Remove(m,n) is convenient to process string data, isn't it? And Environmental.NewLine seems to be a line feed code. There are many things I don't know!
The tapped file in the file list of the previous FileIO page can be edited and saved in this page. Used a small technique to display a border line around the text input area of the Editor control.
Ran this sample App on iOS simulator:
The folder list are displayed in FolderIO page.
File IO page.
Editing file, Test1.txt, in the EditFile page.
As mentioned above, I studied various aspects of folder and file I/O of PCS Storage.
I found that there are some ways to save data processed in App.
- Store data in Cloud, such as Azure and OneDrive
- Link with Web service
- Use local SQLite database
- Use the file system plugin, PCL Storage
- Dictionary Properties(?)
Cloud or Web service is the best choice to save various type of data, but it will be necessary to save data in device. So, firstly, I started to study PCL Storage.
MainPage.xaml
<?xml version="1.0" encoding="UTF-8"?>
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:PCLStrg;assembly=PCLStrg"
x:Class="PCLStrg.MainPage">
<!-- 1st tabbed page: Folder I/O -->
<local:FolderIO />
<!-- 2nd tabbed page: File I/O -->
<local:FileIO />
</TabbedPage>
(The source code is also here.)
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:local="clr-namespace:PCLStrg;assembly=PCLStrg"
x:Class="PCLStrg.MainPage">
<!-- 1st tabbed page: Folder I/O -->
<local:FolderIO />
<!-- 2nd tabbed page: File I/O -->
<local:FileIO />
</TabbedPage>
This sample App is composed of two tabbed pages, and processing example of folder and file I/O has been implemented to the pages respectively.
MainPage.xaml.cs
using Xamarin.Forms;
namespace PCLStrg
{
public partial class MainPage : TabbedPage
{
public MainPage()
{
InitializeComponent();
}
}
}
namespace PCLStrg
{
public partial class MainPage : TabbedPage
{
public MainPage()
{
InitializeComponent();
}
}
}
App.xaml.cs
using Xamarin.Forms;
namespace PCLStrg
{
public partial class App : Application
{
public App()
{
InitializeComponent();
//MainPage = new MainPage();
MainPage = new NavigationPage(new MainPage());
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
namespace PCLStrg
{
public partial class App : Application
{
public App()
{
InitializeComponent();
//MainPage = new MainPage();
MainPage = new NavigationPage(new MainPage());
}
protected override void OnStart()
{
// Handle when your app starts
}
protected override void OnSleep()
{
// Handle when your app sleeps
}
protected override void OnResume()
{
// Handle when your app resumes
}
}
}
I explain how to build folder and file I/O below.
FolderIO.xaml
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PCLStrg.FolderIO" Title="Folder I/O" Icon="Folder.png">
<ContentPage.Content>
<StackLayout Margin="0, 30, 0, 50">
<Label Text="PCL Storage Folder and File I/O Sample App" />
<Label Text=" --- Folder I/O ---" />
<!-- Display Current Directory -->
<Button Text="RootFolder Info." Clicked="DisplayRootFolder" HorizontalOptions="Start" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<!-- Create a new Folder -->
<StackLayout Orientation="Horizontal">
<Button Text="Create Folder" Clicked="CreateFolder" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1">
<!-- Enable Button, if Entry gets text input -->
<Button.Triggers>
<DataTrigger TargetType="Button" Binding="{Binding Source={x:Reference EntCreateFolder}, Path=Text.Length}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Button.Triggers>
</Button>
<Entry x:Name="EntCreateFolder" Placeholder="Input SubFolder Name" Text="" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Check Folder Existence -->
<StackLayout Orientation="Horizontal">
<Button Text="Check Folder" Clicked="CheckFolder" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<Entry x:Name="EntCheckFolder" Placeholder="Input SubFolder Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Delete Folder -->
<StackLayout Orientation="Horizontal">
<Button Text="Delete Folder" Clicked="DeleteFolder" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<Entry x:Name="EntDeleteFolder" Placeholder="Input SubFolder Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Display All Folders -->
<Button Text="Show Folders" Clicked="GetFolders" HorizontalOptions="Start" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<!-- Display Folder I/O Results -->
<Label Text=" --- Folder I/O Results ---" />
<ListView x:Name="FolderIOResult" ItemTapped="TappedResultItem" HasUnevenRows="false" RowHeight="25"/>
<Button Text="Clear Result in the above List" Clicked="ClearFolderIOResult" HorizontalOptions="Center" WidthRequest="250" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
</StackLayout>
</ContentPage.Content>
<!-- Change color, if Entry is focused -->
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Entry">
<Style.Triggers>
<Trigger TargetType="Entry" Property="IsFocused" Value="True">
<Setter Property="BackgroundColor" Value="Aqua" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
</ContentPage>
x:Class="PCLStrg.FolderIO" Title="Folder I/O" Icon="Folder.png">
<ContentPage.Content>
<StackLayout Margin="0, 30, 0, 50">
<Label Text="PCL Storage Folder and File I/O Sample App" />
<Label Text=" --- Folder I/O ---" />
<!-- Display Current Directory -->
<Button Text="RootFolder Info." Clicked="DisplayRootFolder" HorizontalOptions="Start" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<!-- Create a new Folder -->
<StackLayout Orientation="Horizontal">
<Button Text="Create Folder" Clicked="CreateFolder" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1">
<!-- Enable Button, if Entry gets text input -->
<Button.Triggers>
<DataTrigger TargetType="Button" Binding="{Binding Source={x:Reference EntCreateFolder}, Path=Text.Length}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Button.Triggers>
</Button>
<Entry x:Name="EntCreateFolder" Placeholder="Input SubFolder Name" Text="" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Check Folder Existence -->
<StackLayout Orientation="Horizontal">
<Button Text="Check Folder" Clicked="CheckFolder" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<Entry x:Name="EntCheckFolder" Placeholder="Input SubFolder Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Delete Folder -->
<StackLayout Orientation="Horizontal">
<Button Text="Delete Folder" Clicked="DeleteFolder" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<Entry x:Name="EntDeleteFolder" Placeholder="Input SubFolder Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Display All Folders -->
<Button Text="Show Folders" Clicked="GetFolders" HorizontalOptions="Start" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<!-- Display Folder I/O Results -->
<Label Text=" --- Folder I/O Results ---" />
<ListView x:Name="FolderIOResult" ItemTapped="TappedResultItem" HasUnevenRows="false" RowHeight="25"/>
<Button Text="Clear Result in the above List" Clicked="ClearFolderIOResult" HorizontalOptions="Center" WidthRequest="250" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
</StackLayout>
</ContentPage.Content>
<!-- Change color, if Entry is focused -->
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Entry">
<Style.Triggers>
<Trigger TargetType="Entry" Property="IsFocused" Value="True">
<Setter Property="BackgroundColor" Value="Aqua" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
</ContentPage>
Get the current folder path, create new folders, check folders already exists, delete folders are implemented in this Folder I/O tabbed page. The results of the processing are displayed in the ListView set at the bottom of the page.
I used Trigger function on some Entry and Button control to enhance their effect.
FolderIO.xaml.cs
using System;
using System.Collections;
using System.Collections.Generic;
using Xamarin.Forms;
using PCLStorage;
namespace PCLStrg
{
public partial class FolderIO : ContentPage
{
public FolderIO()
{
InitializeComponent();
}
//Get Root Folder Path
IFolder rootFolder = FileSystem.Current.LocalStorage;
//
// Folder I/O
//
//Display Root Folder's Name and Path
void DisplayRootFolder(object sender, EventArgs e)
{
string[] RootFolderInfo = new string[]
{
"Root Folder Name:",
" - " + rootFolder.Name,
"Root Folder Path:",
" - " + rootFolder.Path
};
DisplayResult(FolderIOResult, RootFolderInfo);
}
//Create a new Folder
async void CreateFolder(object sender, EventArgs e)
{
var Entry = EntCreateFolder;
// Alert, if no Folder Name
if (Entry.Text == null)
{
await DisplayAlert("Create Subfolder", "Input Subfolder Name!", "OK");
return;
}
// Create a new Folder named in EntCreateSubFolder
IFolder subfolder =
await rootFolder.CreateFolderAsync(Entry.Text, CreationCollisionOption.OpenIfExists);
await DisplayAlert("Create Subfolder", Entry.Text + " has been created successfully!", "OK");
}
//Check Folder Existence
async void CheckFolder(object sender, EventArgs e)
{
var Entry = EntCheckFolder;
// Alert, if no Folder Name
if (Entry.Text == null)
{
await DisplayAlert("Check Folder Result", "Input Folder Name!", "OK");
return;
}
// Check Folder Existence entered in EntCheckSubFolder
var subfolderExists = await rootFolder.CheckExistsAsync(Entry.Text);
if (subfolderExists != ExistenceCheckResult.FolderExists)
{
await DisplayAlert("Check Folder Result", Entry.Text + " doesn't exist", "OK");
return;
}
await DisplayAlert("Check Folder Result", Entry.Text + " exists!", "OK");
}
//Delete Folder
async void DeleteFolder(object sender, EventArgs e)
{
var Entry = EntDeleteFolder;
// Alert, if SubFolder Name was not entered
if (Entry.Text == null)
{
await DisplayAlert("Delete Folder Result", "Input Folder Name!", "OK");
return;
}
// Delete Folder entered in EntDeleteSubFolder
var subfolderExists = await rootFolder.CheckExistsAsync(Entry.Text);
if (subfolderExists != ExistenceCheckResult.FolderExists)
{
await DisplayAlert("Delete Folder Result", Entry.Text + " doesn't exist", "OK");
return;
}
IFolder subfolder = await rootFolder.GetFolderAsync(Entry.Text);
await subfolder.DeleteAsync();
await DisplayAlert("Delete Folder Result", Entry.Text + " has been deleted!", "OK");
}
// Get & Display Folders list
async void GetFolders(object sender, EventArgs e)
{
//Get the Folders list
IList<IFolder> folders = await rootFolder.GetFoldersAsync();
//Get all Folder name as string data
IEnumerator foldersList = folders.GetEnumerator();
int i = 0;
string[] folderName = new string[10];
folderName[i] = "Subfolders in the Root Folder:"; i++;
while (foldersList.MoveNext())
{
IFolder val = (IFolder)foldersList.Current;
folderName[i] = " - " + val.Name;
i++;
}
//The number of Folders
folderName[i] = "// " + folders.Count.ToString() + " subfolders";
//Display Folder names and the number of them
DisplayResult(FolderIOResult, folderName);
}
//
// Display & Clear Folder I/O Result
//
//Display the results in ListView
void DisplayResult(ListView ListViewName, string[] result)
{
ListViewName.ItemsSource = result;
}
//Clear all the Folder I/O result
void ClearFolderIOResult(object sender, EventArgs e)
{
FolderIOResult.ItemsSource = null;
}
//Display the tapped Folder
void TappedResultItem(object sender, ItemTappedEventArgs e)
{
DisplayAlert("Item Tapped", e.Item.ToString(), "OK");
}
}
}
using System.Collections;
using System.Collections.Generic;
using Xamarin.Forms;
using PCLStorage;
namespace PCLStrg
{
public partial class FolderIO : ContentPage
{
public FolderIO()
{
InitializeComponent();
}
//Get Root Folder Path
IFolder rootFolder = FileSystem.Current.LocalStorage;
//
// Folder I/O
//
//Display Root Folder's Name and Path
void DisplayRootFolder(object sender, EventArgs e)
{
string[] RootFolderInfo = new string[]
{
"Root Folder Name:",
" - " + rootFolder.Name,
"Root Folder Path:",
" - " + rootFolder.Path
};
DisplayResult(FolderIOResult, RootFolderInfo);
}
//Create a new Folder
async void CreateFolder(object sender, EventArgs e)
{
var Entry = EntCreateFolder;
// Alert, if no Folder Name
if (Entry.Text == null)
{
await DisplayAlert("Create Subfolder", "Input Subfolder Name!", "OK");
return;
}
// Create a new Folder named in EntCreateSubFolder
IFolder subfolder =
await rootFolder.CreateFolderAsync(Entry.Text, CreationCollisionOption.OpenIfExists);
await DisplayAlert("Create Subfolder", Entry.Text + " has been created successfully!", "OK");
}
//Check Folder Existence
async void CheckFolder(object sender, EventArgs e)
{
var Entry = EntCheckFolder;
// Alert, if no Folder Name
if (Entry.Text == null)
{
await DisplayAlert("Check Folder Result", "Input Folder Name!", "OK");
return;
}
// Check Folder Existence entered in EntCheckSubFolder
var subfolderExists = await rootFolder.CheckExistsAsync(Entry.Text);
if (subfolderExists != ExistenceCheckResult.FolderExists)
{
await DisplayAlert("Check Folder Result", Entry.Text + " doesn't exist", "OK");
return;
}
await DisplayAlert("Check Folder Result", Entry.Text + " exists!", "OK");
}
//Delete Folder
async void DeleteFolder(object sender, EventArgs e)
{
var Entry = EntDeleteFolder;
// Alert, if SubFolder Name was not entered
if (Entry.Text == null)
{
await DisplayAlert("Delete Folder Result", "Input Folder Name!", "OK");
return;
}
// Delete Folder entered in EntDeleteSubFolder
var subfolderExists = await rootFolder.CheckExistsAsync(Entry.Text);
if (subfolderExists != ExistenceCheckResult.FolderExists)
{
await DisplayAlert("Delete Folder Result", Entry.Text + " doesn't exist", "OK");
return;
}
IFolder subfolder = await rootFolder.GetFolderAsync(Entry.Text);
await subfolder.DeleteAsync();
await DisplayAlert("Delete Folder Result", Entry.Text + " has been deleted!", "OK");
}
// Get & Display Folders list
async void GetFolders(object sender, EventArgs e)
{
//Get the Folders list
IList<IFolder> folders = await rootFolder.GetFoldersAsync();
//Get all Folder name as string data
IEnumerator foldersList = folders.GetEnumerator();
int i = 0;
string[] folderName = new string[10];
folderName[i] = "Subfolders in the Root Folder:"; i++;
while (foldersList.MoveNext())
{
IFolder val = (IFolder)foldersList.Current;
folderName[i] = " - " + val.Name;
i++;
}
//The number of Folders
folderName[i] = "// " + folders.Count.ToString() + " subfolders";
//Display Folder names and the number of them
DisplayResult(FolderIOResult, folderName);
}
//
// Display & Clear Folder I/O Result
//
//Display the results in ListView
void DisplayResult(ListView ListViewName, string[] result)
{
ListViewName.ItemsSource = result;
}
//Clear all the Folder I/O result
void ClearFolderIOResult(object sender, EventArgs e)
{
FolderIOResult.ItemsSource = null;
}
//Display the tapped Folder
void TappedResultItem(object sender, ItemTappedEventArgs e)
{
DisplayAlert("Item Tapped", e.Item.ToString(), "OK");
}
}
}
IFolder, async/await etc. were a little bit confusing, but I finally made the code shown above.
It was somewhat difficult to display folder list. I found that IEnumerator was useful to do it, and could successfully get folder names as text array data and show them in ListView. But I have not deeply understood IEnumerater yet, and I have to study it.
FileIO.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PCLStrg.FileIO" Title="File I/O" Icon="File.png" >
<ContentPage.Content>
<StackLayout Margin="0, 30, 0, 30">
<Label Text="PCL Storage Folder and File I/O Sample App" />
<Label Text=" --- File I/O ---" />
<!-- Create a new File -->
<StackLayout Orientation="Horizontal">
<Button Text="Create New File" Clicked="CreateFile" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<Entry x:Name="EntCreateFile" Placeholder="Input File Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Check File Existence -->
<StackLayout Orientation="Horizontal">
<Button Text="Check File" Clicked="CheckFile" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<Entry x:Name="EntCheckFile" Placeholder="Input File Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Delete File -->
<StackLayout Orientation="Horizontal">
<Button Text="Delete File" Clicked="DeleteFile" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<Entry x:Name="EntDeleteFile" Placeholder="Input File Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Show All Files -->
<Button Text="Show Files" Clicked="GetFiles" HorizontalOptions="Start" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<!-- Additionally Write Content to File -->
<StackLayout Orientation="Horizontal">
<Button Text="Write File" Clicked="WriteFile" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1">
<!-- Enable Button, if EntWriteFile_Content gets text input -->
<Button.Triggers>
<DataTrigger TargetType="Button" Binding="{Binding Source={x:Reference EntWriteFile_Content}, Path=Text.Length}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Button.Triggers>
</Button>
<StackLayout Margin="0, 0, 0, 0">
<Entry x:Name="EntWriteFile_FileName" Text="" Placeholder="Input File Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
<Entry x:Name="EntWriteFile_Content" Text="" Placeholder="Input Text" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" >
<!-- Enable Ent_WriteFile_Content, if EntWriteFile_FileName gets text input -->
<Entry.Triggers>
<DataTrigger TargetType="Entry" Binding="{Binding Source={x:Reference EntWriteFile_FileName}, Path=Text.Length}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Entry.Triggers>
</Entry>
</StackLayout>
</StackLayout>
<!-- Read File -->
<StackLayout Orientation="Horizontal">
<Button Text="Read File" Clicked="ReadFile" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<Entry x:Name="EntReadFile" Placeholder="Input File Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Display File I/O Results -->
<Label Text=" - - - File I/O Results - - -" />
<!-- <ListView x:Name="FileIOResult" ItemTapped="TappedResultItem" RowHeight="25"> -->
<ListView x:Name="FileIOResult" ItemTapped="TappedResultItem" RowHeight="25">
<!-- Context Actions: MenuItem -->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding .}" />
<ViewCell.ContextActions>
<MenuItem Clicked="MenuEdit" Text="Edit" CommandParameter="{Binding .}" />
<MenuItem Clicked="MenuDelete" Text="Delete" IsDestructive="true" CommandParameter="{Binding .}" />
</ViewCell.ContextActions>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Text="Clear Result in the above List" Clicked="ClearFileIOResult" HorizontalOptions="Center" WidthRequest="250" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
</StackLayout>
</ContentPage.Content>
<!-- Change color, if Entry is focused -->
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Entry">
<Style.Triggers>
<Trigger TargetType="Entry" Property="IsFocused" Value="True">
<Setter Property="BackgroundColor" Value="Aqua" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
</ContentPage>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PCLStrg.FileIO" Title="File I/O" Icon="File.png" >
<ContentPage.Content>
<StackLayout Margin="0, 30, 0, 30">
<Label Text="PCL Storage Folder and File I/O Sample App" />
<Label Text=" --- File I/O ---" />
<!-- Create a new File -->
<StackLayout Orientation="Horizontal">
<Button Text="Create New File" Clicked="CreateFile" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<Entry x:Name="EntCreateFile" Placeholder="Input File Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Check File Existence -->
<StackLayout Orientation="Horizontal">
<Button Text="Check File" Clicked="CheckFile" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<Entry x:Name="EntCheckFile" Placeholder="Input File Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Delete File -->
<StackLayout Orientation="Horizontal">
<Button Text="Delete File" Clicked="DeleteFile" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<Entry x:Name="EntDeleteFile" Placeholder="Input File Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Show All Files -->
<Button Text="Show Files" Clicked="GetFiles" HorizontalOptions="Start" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<!-- Additionally Write Content to File -->
<StackLayout Orientation="Horizontal">
<Button Text="Write File" Clicked="WriteFile" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1">
<!-- Enable Button, if EntWriteFile_Content gets text input -->
<Button.Triggers>
<DataTrigger TargetType="Button" Binding="{Binding Source={x:Reference EntWriteFile_Content}, Path=Text.Length}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Button.Triggers>
</Button>
<StackLayout Margin="0, 0, 0, 0">
<Entry x:Name="EntWriteFile_FileName" Text="" Placeholder="Input File Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
<Entry x:Name="EntWriteFile_Content" Text="" Placeholder="Input Text" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" >
<!-- Enable Ent_WriteFile_Content, if EntWriteFile_FileName gets text input -->
<Entry.Triggers>
<DataTrigger TargetType="Entry" Binding="{Binding Source={x:Reference EntWriteFile_FileName}, Path=Text.Length}" Value="0">
<Setter Property="IsEnabled" Value="False" />
</DataTrigger>
</Entry.Triggers>
</Entry>
</StackLayout>
</StackLayout>
<!-- Read File -->
<StackLayout Orientation="Horizontal">
<Button Text="Read File" Clicked="ReadFile" WidthRequest="150" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<Entry x:Name="EntReadFile" Placeholder="Input File Name" Keyboard="Text" HeightRequest="30" HorizontalOptions="FillAndExpand" />
</StackLayout>
<!-- Display File I/O Results -->
<Label Text=" - - - File I/O Results - - -" />
<!-- <ListView x:Name="FileIOResult" ItemTapped="TappedResultItem" RowHeight="25"> -->
<ListView x:Name="FileIOResult" ItemTapped="TappedResultItem" RowHeight="25">
<!-- Context Actions: MenuItem -->
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
<Label Text="{Binding .}" />
<ViewCell.ContextActions>
<MenuItem Clicked="MenuEdit" Text="Edit" CommandParameter="{Binding .}" />
<MenuItem Clicked="MenuDelete" Text="Delete" IsDestructive="true" CommandParameter="{Binding .}" />
</ViewCell.ContextActions>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
<Button Text="Clear Result in the above List" Clicked="ClearFileIOResult" HorizontalOptions="Center" WidthRequest="250" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
</StackLayout>
</ContentPage.Content>
<!-- Change color, if Entry is focused -->
<ContentPage.Resources>
<ResourceDictionary>
<Style TargetType="Entry">
<Style.Triggers>
<Trigger TargetType="Entry" Property="IsFocused" Value="True">
<Setter Property="BackgroundColor" Value="Aqua" />
</Trigger>
</Style.Triggers>
</Style>
</ResourceDictionary>
</ContentPage.Resources>
</ContentPage>
In addition to create and delete files like folder I/O, read file contents and additionally write contents to file were also implemented. In display of file list, added MenuItem context actions, and move to the EditFile page explained later and delete file are available in it.
FileIO.xaml.cs
using System;
using System.Collections;
using System.Collections.Generic;
using Xamarin.Forms;
using PCLStorage;
namespace PCLStrg
{
public partial class FileIO : ContentPage
{
public FileIO()
{
InitializeComponent();
}
//Get Root Folder Path
IFolder rootFolder = FileSystem.Current.LocalStorage;
//
// File I/O
//
//Create a new File
async void CreateFile(object sender, EventArgs e)
{
var Entry = EntCreateFile;
// Alert, if no File Name
if (Entry.Text == null)
{
await DisplayAlert("Create File", "Input File Name!", "OK");
return;
}
// Create a new File named in EntCreateFile
IFile newFile =
await rootFolder.CreateFileAsync(Entry.Text, CreationCollisionOption.OpenIfExists);
await DisplayAlert("Create File", Entry.Text + " has been created successfully!", "OK");
}
//Check File Existence
async void CheckFile(object sender, EventArgs e)
{
var Entry = EntCheckFile;
// Alert, if no File name
if (Entry.Text == null)
{
await DisplayAlert("Check File", "Input File Name!", "OK");
return;
}
// Check File Existence entered in EntCheckFile
var fileExists = await rootFolder.CheckExistsAsync(Entry.Text);
if (fileExists != ExistenceCheckResult.FileExists)
{
await DisplayAlert("Check File", Entry.Text + " doesn't exist", "OK");
return;
}
await DisplayAlert("Check File", Entry.Text + " exists!", "OK");
}
//Delete File
async void DeleteFile(object sender, EventArgs e)
{
var Entry = EntDeleteFile;
// Alert, if no File Name
if (Entry.Text == null)
{
await DisplayAlert("Delete File", "Input File Name!", "OK");
return;
}
// Delete File entered in EntDeleteSubFolder
var fileExists = await rootFolder.CheckExistsAsync(Entry.Text);
if (fileExists != ExistenceCheckResult.FileExists)
{
await DisplayAlert("Delete File", Entry.Text + " doesn't exist", "OK");
return;
}
IFile file = await rootFolder.GetFileAsync(Entry.Text);
await file.DeleteAsync();
await DisplayAlert("Delete File", Entry.Text + " has been deleted!", "OK");
}
// Get & Display File list
async void GetFiles(object sender, EventArgs e)
{
//Get File list
IList<IFile> files = await rootFolder.GetFilesAsync();
//Get all File Name as string data
IEnumerator filesList = files.GetEnumerator();
int i = 0;
string[] fileName = new string[10];
fileName[i] = "Files in the Root Folder:"; i++;
while (filesList.MoveNext())
{
IFile val = (IFile)filesList.Current;
fileName[i] = " - " + val.Name;
i++;
}
//The number of Files
fileName[i] = "// " + files.Count.ToString() + " files";
//Display File names and the number of them
DisplayResult(FileIOResult, fileName);
}
// Additionally Write text to File
async void WriteFile(object sender, EventArgs e)
{
var Entry_FileName = EntWriteFile_FileName;
var Entry_Content = EntWriteFile_Content;
string content = "";
// Alert, if no File Name
if (Entry_FileName.Text == null)
{
await DisplayAlert("Check File", "Input File Name!", "OK");
return;
}
// Check File Existence entered in EntWriteFile
var fileExists = await rootFolder.CheckExistsAsync(Entry_FileName.Text);
if (fileExists != ExistenceCheckResult.FileExists)
{
// Create&Write File or Quit App, if File doesn't exist
if (await DisplayAlert("Write File", "File doesn' exist", "Create?", "No"))
{
IFile file1 = await rootFolder.CreateFileAsync(Entry_FileName.Text, CreationCollisionOption.OpenIfExists);
await file1.WriteAllTextAsync(Entry_Content.Text);
}
return;
}
// Add new content to existing content
IFile file = await rootFolder.CreateFileAsync(Entry_FileName.Text, CreationCollisionOption.OpenIfExists);
content = await file.ReadAllTextAsync();
await file.WriteAllTextAsync(content + Environment.NewLine + Entry_Content.Text);
}
//Read File
async void ReadFile(object sender, EventArgs e)
{
var Entry = EntReadFile;
string content = "";
// Alert, if no File Name
if (Entry.Text == null)
{
await DisplayAlert("Read File", "Input File Name!", "OK");
return;
}
// Read File entered in EntReadFile
var fileExists = await rootFolder.CheckExistsAsync(Entry.Text);
if (fileExists != ExistenceCheckResult.FileExists)
{
await DisplayAlert("Delete File", Entry.Text + " doesn't exist", "OK");
return;
}
IFile file = await rootFolder.GetFileAsync(Entry.Text);
content = await file.ReadAllTextAsync();
await DisplayAlert("Read File", content, "OK");
}
//
// Edit & Delete File from Menu Context Actions
//
async void MenuEdit(object sender, EventArgs e)
{
var item = (MenuItem)sender;
// Move EditFile page
await Navigation.PushAsync(new EditFile(item.CommandParameter.ToString()));
}
async void MenuDelete(object sender, EventArgs e)
{
var item = (MenuItem)sender;
IFile file = await rootFolder.GetFileAsync(item.CommandParameter.ToString().Remove(0, 7));
// Delete File
await file.DeleteAsync();
// Re-Display List
GetFiles(null, null);
await DisplayAlert("Delete File", item.CommandParameter + " has been deleted!", "OK");
}
//
// Display and Clear File I/O Result
//
//Display the results in ListView
void DisplayResult(ListView ListViewName, string[] result)
{
ListViewName.ItemsSource = result;
}
//Clear all the File I/O result
void ClearFileIOResult(object sender, EventArgs e)
{
FileIOResult.ItemsSource = null;
}
//Display the tapped File in EditFile page
async void TappedResultItem(object sender, ItemTappedEventArgs e)
{
await Navigation.PushAsync(new EditFile(e.Item.ToString()));
}
}
}
using System.Collections;
using System.Collections.Generic;
using Xamarin.Forms;
using PCLStorage;
namespace PCLStrg
{
public partial class FileIO : ContentPage
{
public FileIO()
{
InitializeComponent();
}
//Get Root Folder Path
IFolder rootFolder = FileSystem.Current.LocalStorage;
//
// File I/O
//
//Create a new File
async void CreateFile(object sender, EventArgs e)
{
var Entry = EntCreateFile;
// Alert, if no File Name
if (Entry.Text == null)
{
await DisplayAlert("Create File", "Input File Name!", "OK");
return;
}
// Create a new File named in EntCreateFile
IFile newFile =
await rootFolder.CreateFileAsync(Entry.Text, CreationCollisionOption.OpenIfExists);
await DisplayAlert("Create File", Entry.Text + " has been created successfully!", "OK");
}
//Check File Existence
async void CheckFile(object sender, EventArgs e)
{
var Entry = EntCheckFile;
// Alert, if no File name
if (Entry.Text == null)
{
await DisplayAlert("Check File", "Input File Name!", "OK");
return;
}
// Check File Existence entered in EntCheckFile
var fileExists = await rootFolder.CheckExistsAsync(Entry.Text);
if (fileExists != ExistenceCheckResult.FileExists)
{
await DisplayAlert("Check File", Entry.Text + " doesn't exist", "OK");
return;
}
await DisplayAlert("Check File", Entry.Text + " exists!", "OK");
}
//Delete File
async void DeleteFile(object sender, EventArgs e)
{
var Entry = EntDeleteFile;
// Alert, if no File Name
if (Entry.Text == null)
{
await DisplayAlert("Delete File", "Input File Name!", "OK");
return;
}
// Delete File entered in EntDeleteSubFolder
var fileExists = await rootFolder.CheckExistsAsync(Entry.Text);
if (fileExists != ExistenceCheckResult.FileExists)
{
await DisplayAlert("Delete File", Entry.Text + " doesn't exist", "OK");
return;
}
IFile file = await rootFolder.GetFileAsync(Entry.Text);
await file.DeleteAsync();
await DisplayAlert("Delete File", Entry.Text + " has been deleted!", "OK");
}
// Get & Display File list
async void GetFiles(object sender, EventArgs e)
{
//Get File list
IList<IFile> files = await rootFolder.GetFilesAsync();
//Get all File Name as string data
IEnumerator filesList = files.GetEnumerator();
int i = 0;
string[] fileName = new string[10];
fileName[i] = "Files in the Root Folder:"; i++;
while (filesList.MoveNext())
{
IFile val = (IFile)filesList.Current;
fileName[i] = " - " + val.Name;
i++;
}
//The number of Files
fileName[i] = "// " + files.Count.ToString() + " files";
//Display File names and the number of them
DisplayResult(FileIOResult, fileName);
}
// Additionally Write text to File
async void WriteFile(object sender, EventArgs e)
{
var Entry_FileName = EntWriteFile_FileName;
var Entry_Content = EntWriteFile_Content;
string content = "";
// Alert, if no File Name
if (Entry_FileName.Text == null)
{
await DisplayAlert("Check File", "Input File Name!", "OK");
return;
}
// Check File Existence entered in EntWriteFile
var fileExists = await rootFolder.CheckExistsAsync(Entry_FileName.Text);
if (fileExists != ExistenceCheckResult.FileExists)
{
// Create&Write File or Quit App, if File doesn't exist
if (await DisplayAlert("Write File", "File doesn' exist", "Create?", "No"))
{
IFile file1 = await rootFolder.CreateFileAsync(Entry_FileName.Text, CreationCollisionOption.OpenIfExists);
await file1.WriteAllTextAsync(Entry_Content.Text);
}
return;
}
// Add new content to existing content
IFile file = await rootFolder.CreateFileAsync(Entry_FileName.Text, CreationCollisionOption.OpenIfExists);
content = await file.ReadAllTextAsync();
await file.WriteAllTextAsync(content + Environment.NewLine + Entry_Content.Text);
}
//Read File
async void ReadFile(object sender, EventArgs e)
{
var Entry = EntReadFile;
string content = "";
// Alert, if no File Name
if (Entry.Text == null)
{
await DisplayAlert("Read File", "Input File Name!", "OK");
return;
}
// Read File entered in EntReadFile
var fileExists = await rootFolder.CheckExistsAsync(Entry.Text);
if (fileExists != ExistenceCheckResult.FileExists)
{
await DisplayAlert("Delete File", Entry.Text + " doesn't exist", "OK");
return;
}
IFile file = await rootFolder.GetFileAsync(Entry.Text);
content = await file.ReadAllTextAsync();
await DisplayAlert("Read File", content, "OK");
}
//
// Edit & Delete File from Menu Context Actions
//
async void MenuEdit(object sender, EventArgs e)
{
var item = (MenuItem)sender;
// Move EditFile page
await Navigation.PushAsync(new EditFile(item.CommandParameter.ToString()));
}
async void MenuDelete(object sender, EventArgs e)
{
var item = (MenuItem)sender;
IFile file = await rootFolder.GetFileAsync(item.CommandParameter.ToString().Remove(0, 7));
// Delete File
await file.DeleteAsync();
// Re-Display List
GetFiles(null, null);
await DisplayAlert("Delete File", item.CommandParameter + " has been deleted!", "OK");
}
//
// Display and Clear File I/O Result
//
//Display the results in ListView
void DisplayResult(ListView ListViewName, string[] result)
{
ListViewName.ItemsSource = result;
}
//Clear all the File I/O result
void ClearFileIOResult(object sender, EventArgs e)
{
FileIOResult.ItemsSource = null;
}
//Display the tapped File in EditFile page
async void TappedResultItem(object sender, ItemTappedEventArgs e)
{
await Navigation.PushAsync(new EditFile(e.Item.ToString()));
}
}
}
By the way, text.Remove(m,n) is convenient to process string data, isn't it? And Environmental.NewLine seems to be a line feed code. There are many things I don't know!
EditFile.xaml
<?xml version="1.0" encoding="UTF-8"?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PCLStrg.EditFile">
<ContentPage.Content>
<StackLayout BackgroundColor="white" >
<StackLayout Orientation="Horizontal" VerticalOptions="Center" >
<Label Text="Tapped File: " />
<Label x:Name="TappedFileName" HeightRequest="25"/>
</StackLayout>
<!-- Edit File Contents -->
<StackLayout BackgroundColor="gray" Padding="1" Margin="20,0,0,0" HorizontalOptions="Start" WidthRequest="300" HeightRequest="300" >
<Editor x:Name="FileContent" BackgroundColor="white" HorizontalOptions="Start" WidthRequest="300" HeightRequest="300" />
</StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="Center" >
<!-- Save File -->
<Button Margin="20,0,0,0" Text="save" Clicked="SaveFile" HorizontalOptions="Start" WidthRequest="60" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<!-- not Save File -->
<Button Margin="3,0,0,0" Text="don't save" Clicked="NotSaveFile" HorizontalOptions="Start" WidthRequest="100" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<!-- Close File -->
<Button Margin="3,0,0,0" Text="close" Clicked="CloseFile" HorizontalOptions="Start" WidthRequest="60" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms" xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="PCLStrg.EditFile">
<ContentPage.Content>
<StackLayout BackgroundColor="white" >
<StackLayout Orientation="Horizontal" VerticalOptions="Center" >
<Label Text="Tapped File: " />
<Label x:Name="TappedFileName" HeightRequest="25"/>
</StackLayout>
<!-- Edit File Contents -->
<StackLayout BackgroundColor="gray" Padding="1" Margin="20,0,0,0" HorizontalOptions="Start" WidthRequest="300" HeightRequest="300" >
<Editor x:Name="FileContent" BackgroundColor="white" HorizontalOptions="Start" WidthRequest="300" HeightRequest="300" />
</StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="Center" >
<!-- Save File -->
<Button Margin="20,0,0,0" Text="save" Clicked="SaveFile" HorizontalOptions="Start" WidthRequest="60" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<!-- not Save File -->
<Button Margin="3,0,0,0" Text="don't save" Clicked="NotSaveFile" HorizontalOptions="Start" WidthRequest="100" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
<!-- Close File -->
<Button Margin="3,0,0,0" Text="close" Clicked="CloseFile" HorizontalOptions="Start" WidthRequest="60" HeightRequest="30" BorderColor="Blue" BorderWidth="1" />
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>
The tapped file in the file list of the previous FileIO page can be edited and saved in this page. Used a small technique to display a border line around the text input area of the Editor control.
EditFile.xaml.cs
using System;
using Xamarin.Forms;
using PCLStorage;
namespace PCLStrg
{
public partial class EditFile : ContentPage
{
public EditFile(string filename)
{
InitializeComponent();
// Get File Name tapped in the List
TappedFileName.Text = filename.Remove(0, 7);
// Read File Contents and Bind Editor control
ImportFile();
}
// Get Root Folder Path
IFolder rootFolder = FileSystem.Current.LocalStorage;
public string content0;
// Read File Contents and Bind Editor Control
async void ImportFile()
{
IFile file = await rootFolder.GetFileAsync(TappedFileName.Text);
string content = await file.ReadAllTextAsync();
content0 = content;
FileContent.Text = content;
}
// Save File
async void SaveFile(object sender, EventArgs e)
{
IFile file = await rootFolder.CreateFileAsync(TappedFileName.Text, CreationCollisionOption.OpenIfExists);
await file.WriteAllTextAsync(FileContent.Text);
await DisplayAlert("File Content", TappedFileName.Text + " has been saved successfully!", "OK");
}
// not Save File
async void NotSaveFile(object sender, EventArgs e)
{
IFile file = await rootFolder.CreateFileAsync(TappedFileName.Text, CreationCollisionOption.OpenIfExists);
await file.WriteAllTextAsync(content0);
await DisplayAlert("File Content", TappedFileName.Text + " has not been saved!", "OK");
await Navigation.PushAsync(new FileIO());
}
// Close File (Back to File I/O page)
async void CloseFile(object sender, EventArgs e)
{
await Navigation.PushAsync(new FileIO());
}
}
}
using Xamarin.Forms;
using PCLStorage;
namespace PCLStrg
{
public partial class EditFile : ContentPage
{
public EditFile(string filename)
{
InitializeComponent();
// Get File Name tapped in the List
TappedFileName.Text = filename.Remove(0, 7);
// Read File Contents and Bind Editor control
ImportFile();
}
// Get Root Folder Path
IFolder rootFolder = FileSystem.Current.LocalStorage;
public string content0;
// Read File Contents and Bind Editor Control
async void ImportFile()
{
IFile file = await rootFolder.GetFileAsync(TappedFileName.Text);
string content = await file.ReadAllTextAsync();
content0 = content;
FileContent.Text = content;
}
// Save File
async void SaveFile(object sender, EventArgs e)
{
IFile file = await rootFolder.CreateFileAsync(TappedFileName.Text, CreationCollisionOption.OpenIfExists);
await file.WriteAllTextAsync(FileContent.Text);
await DisplayAlert("File Content", TappedFileName.Text + " has been saved successfully!", "OK");
}
// not Save File
async void NotSaveFile(object sender, EventArgs e)
{
IFile file = await rootFolder.CreateFileAsync(TappedFileName.Text, CreationCollisionOption.OpenIfExists);
await file.WriteAllTextAsync(content0);
await DisplayAlert("File Content", TappedFileName.Text + " has not been saved!", "OK");
await Navigation.PushAsync(new FileIO());
}
// Close File (Back to File I/O page)
async void CloseFile(object sender, EventArgs e)
{
await Navigation.PushAsync(new FileIO());
}
}
}
Ran this sample App on iOS simulator:
The folder list are displayed in FolderIO page.
File IO page.
Editing file, Test1.txt, in the EditFile page.
As mentioned above, I studied various aspects of folder and file I/O of PCS Storage.
コメント
コメントを投稿