# Xamarin.Form 學習筆記
###### tags: `xamarin`,`form`,`intern`
:::info
* [.gitignore](https://github.com/xamarin/xamarin-forms-samples/blob/master/.gitignore) 很重要~~~
* [build Xamarin.Form on Mac](https://docs.microsoft.com/en-us/xamarin/xamarin-forms/get-started/hello-xamarin-forms/quickstart?tabs=vsmac)
* [c# coding convention](https://docs.microsoft.com/en-us/dotnet/csharp/programming-guide/inside-a-program/coding-conventions)
* [Icons - FontAwesome](https://vulcanlee.gitbooks.io/xamarin-forms/content/FontAwesome.html)
* [Free provisioning for Xamarin.iOS apps](https://docs.microsoft.com/en-us/xamarin/ios/get-started/installation/device-provisioning/free-provisioning?tabs=vsmac)
* [singleton](https://gitlab.com/dentall/haku-xamarin/merge_requests/13/diffs)
:::
### Data Binding
Forms會在 `.xaml` 裡直接使用 viewmodel 中 public instance 的名字
跪著看 Victor 研究出來的[正確用法](https://gitlab.com/dentall/haku-xamarin/merge_requests/10/diffs)吧XD
#### view
`.xaml`
```htmlmixed
<ListView ItemsSource="{Binding Mt}">
```
`.xaml.cs`
```csharp
public SearchPageViewModel ViewModel { get; } = new SearchPageViewModel();
public SearchPage()
{
InitializeComponent();
BindingContext = ViewModel; // DEADLY IMPORTANT !!!
}
```
#### viewModel
```csharp=
public class SearchPageViewModel : BindableObject
{
public static DbManager dbManager =
(DbManager)Application.Current.Properties["_DbManager"];
private ObservableCollection<MedicalTreatment> _mt;
public ObservableCollection<MedicalTreatment> Mt
{
get
{
return _mt;
}
set
{
_mt = value;
OnPropertyChanged();
}
}
public SearchPageViewModel()
{
Mt = new ObservableCollection<MedicalTreatment>();
}
}
```
### Override Object default properties
```htmlembedded
<ResourceDictionary>
<Color x:Key="TextBlack">#232528</Color>
<Style TargetType="Label">
<Setter Property="TextColor"
Value="{StaticResource TextBlack}"/>
</Style>
</ResourceDictionary>
```
### Secure Storage Plugin
Xamarin.Forms 想存機密資料的話,方式和uwp不一樣喔! (跟 `Windows.Security.Credentials` 分手吧XD)
[stackOverflow](https://stackoverflow.com/questions/43365516/how-to-store-user-login-credential-in-xamarin-form)
>https://hyperpad.zendesk.com/hc/en-us/articles/204378199-Create-a-Distribution-Provisioning-Profile
### ListView
> `HasUnevenRows` 超級無敵重要!!!!
> 否則他只會顯示他想顯示的(讓全部擠成一樣高><
```htmlmixed
<ListView ItemsSource="{Binding UserTreatmentList}"
HasUnevenRows="true">
<ListView.ItemTemplate>
<DataTemplate>
<ViewCell>
</ViewCell>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
```
### Entry - AutoCapitalize
iOS 的 Entry 會自動讓輸入的字首大寫
想移掉的話可參考>> [stackOverFlow](https://stackoverflow.com/questions/39983468/is-there-a-way-to-disable-auto-capitalisation-on-xamarin-forms-entry-xaml)
```htmlmixed=
<ContentPage.Resources>
<ResourceDictionary>
<Keyboard x:Key="NoCapitalizationKeyboard"
x:FactoryMethod="Create">
<x:Arguments>
<KeyboardFlags>None</KeyboardFlags>
</x:Arguments>
</Keyboard>
</ResourceDictionary>
</ContentPage.Resources>
<!-- usage -->
<Entry Keyboard="{StaticResource NoCapitalizationKeyboard}" />
```
### Multi-language (localization)
[youtube tutorial](https://www.youtube.com/watch?v=Kfp4pc2elTU)
[github sample code](https://github.com/xamarin/xamarin-forms-samples/tree/master/UsingResxLocalization/UsingResxLocalization/Resx)
> > Unfortunately there is no built-in RESX editor in Visual Studio for Mac.
> > [官方說法](https://docs.microsoft.com/zh-tw/xamarin/xamarin-forms/app-fundamentals/localization/text?tabs=vsmac#globalizing-xamarinforms-code)
>
> 殺了我8 [name=徐遠志]
1. install NUget Package `Plugin.Multilingual`
2. add folder `Helper` with a class `TranslateExtension` inside
3. add folder `Resources` with some localized resource files
```htmlmixed
<data name="ClinicInfo" xml:space="preserve">
<value>診所資料</value>
<comment>NamePage_admin Title</comment>
</data>
```
usage in `.xaml`:
```htmlmixed=
xmlns:i18n="clr-namespace:preProduct.Helpers;assembly=preProduct"
<Label Text="{i18n:Translate ClinicInfo}"/>
```
usage in `.xaml.cs`:
```csharp
using preProduct.Resources;
var ItemName = AppResources.Setting
```
### Layout
[Youtube Lesson - Page and view](https://www.youtube.com/watch?v=5hU-86QFngc)
[Youtube lesson - Layout](https://www.youtube.com/watch?v=PVX0Wv_9kuA)
[reference](http://xforms-kickstarter.com/#layout-options)
`Expand` is used whenever there is more space
```htmlmixed
<!-- 置底 -->
<StackLayout VerticalOptions="End"/>
<!-- 若畫面還有空位,則放置於畫面的最底端 -->
<StackLayout VerticalOptions="EndAndExpand"/>
```
### BackGround Image
###### 方法一
利用 `Grid` 的覆蓋性(同一格的話後面的物件會蓋住前面)
```htmlmixed=
<Grid>
<Image Source="MyItemPicture.png"
Opacity="0.5"
Aspect="Fill"/>
<StackLayout>
<Label Text=""/>
<Label Text=""/>
</StackLayout>
</Grid>
```
###### 方法二
[youtube](https://www.youtube.com/watch?v=NtrFEm68WPw)
```htmlmixed=
<RelativeLayout>
<Image Source="https://www.backgroundImage.png"
RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,Property=Width}"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent,Property=Height}"/>
<StackLayout RelativeLayout.WidthConstraint="{ConstraintExpression Type=RelativeToParent,Property=Width}"
RelativeLayout.HeightConstraint="{ConstraintExpression Type=RelativeToParent,Property=Height}"/>
</RelativeLayout>
```
### ScrollView
[youtube](https://www.youtube.com/watch?v=S8Sog-DsM1U)
```htmlmixed
<!-- `Orientation` defualt is "Vertical" -->
<ScrollView>
<StakLayout>
<!-- 裡面的東西就是頁面要呈現的 -->
</StakLayout>
</ScrollView>
```
### User Preference
> 沒辦法用 `Xamarin.ios` 使用的 `NSUserDefaults`
即使有 reference 到 ios.dll 也會被 throw exception
可是可是 卻終於可以使用 ios 之前不支援的寫法:
```csharp
Application.Current.Properties["userToken"] = token;
```
### Picker
[referrence](https://docs.microsoft.com/zh-tw/xamarin/xamarin-forms/user-interface/picker/populating-itemssource)
.xaml
```htmlmixed
<Picker x:Name="idPicker" Title="choose your Identity"/>
```
.xaml.cs
```csharp
string[] id = {"nurse","doctor","assistant"};
idPicker.ItemSource = id;
```
### Page Navigation
[youtube](https://www.youtube.com/watch?v=vlLdF7zALyQ&t=4s)
* 新增一個 `contentPage (.xaml)`
* 在按鈕事件裡:
```csharp=
async private void LogIn_Clicked(object sender, EventArgs e){
await Navigation.PushAsync(new logInPage());
}
```
* 然後到 `App.xaml.cs` 裡設定 root view
```csharp=
public App()
{
InitializeComponent();
MainPage = new NavigationPage(new MainPage());
//Navigation() 裡面塞 root page
}
```
### Popup Modal
[youtube tutorial](https://www.youtube.com/watch?v=dOU0Qei3Qlk&t=201s)
* import package `Rg.Plugins.Popup`
* 新增一個 `view`
```htmlmixed
xmlns:pages="clr-namespace:Rg.Plugins.Popup.Pages;assembly=Rg.Plugins.Popup"
```
>`clr-namespace: CLR 命名空間`,其宣告位置是在包含要以項目形式公開之公用型別的組件中。
>`assembly= 組件`,其包含部分或全部參考的 CLR 命名空間。 這個值通常只是組件的名稱,而不是路徑,亦不包含副檔名 (例如 .dll 或 .exe)。 您必須將該組件的路徑建立為專案檔中的專案參考,且專案檔中包含您要對應的 XAML。
### Alert
```csharp
await DisplayAlert("Title", "Message", "button text");
```
[referrence](https://docs.microsoft.com/zh-tw/xamarin/xamarin-forms/app-fundamentals/navigation/pop-ups)
### Show Image
put image in:
* `ioS` : Resources
* `Android` : Resources > drawable
```htmlmixed
<Image Source="user.png"/>
```
### 滿版
這樣可以移掉 `Title`
```csharp
NavigationPage.SetHasNavigationBar(this, false);
```
### Restsharp
[reference](https://github.com/restsharp/RestSharp/wiki/Recommended-Usage)
##### POST
```csharp=
public IRestResponse PostLogInInfo(logInInfo data)
{
var json = JsonConvert.SerializeObject(data);
var client = new RestClient(_baseUrl);
var request = new RestRequest("api/authenticate", Method.POST);
request.AddParameter("application/json; charset=utf-8",
json, ParameterType.RequestBody);
request.RequestFormat = DataFormat.Json;
var response = client.Execute(request);
return response;
}
```
### Data Storage
* [data storage - Xamarin University](https://www.youtube.com/watch?v=Xrh6ZJcxtZ8)
* [store data in SQLite](https://hackmd.io/WV_s8NILQG66THJskhJxYw)
### Bottom Navbar
[youtube](https://www.youtube.com/watch?v=Cp_2F621Az0)
[git-example](https://github.com/HoussemDellai/BottomBar-Xamarin-Forms)
### Switch
[youtube](https://www.youtube.com/watch?v=o3tWWdm1ilc)
### 遠志和她的錯誤小夥伴
:::danger
qemu-system-i386 emulator exited unexpected
:::
**發生** Android Emulator 跑不出來(可是沒有顯示Error)
**解法** 右上角的 `Debug >` 換一個 virtual device
:::danger
ibtool exit with code 255
:::
通常是 Xcode太舊或 package未更新
**解法**
1. 關 vs for mac
2. update Xcode
3. open vs for mac and update all packages
4. clean all then run
:::danger
Xamarin.Forms task does not match target
:::
> 出現大量紅線時不要怕
> 先更新所有的 Xamarin.Form package
> 然後關掉 vs for mac 重開就行了
> 如果還是不行就關機
> 睡個覺隔天就好了
>
:::danger
AndroidManifest file does not exist
:::
有時候會不見(可能不小心被自己砍掉之類的
就複製過去就是了