Initial generation of QR Code implemented. App now uses tabs.

This commit is contained in:
Andrey Shabarshov 2021-12-04 16:38:24 +00:00
parent 11f751ed23
commit c4d1013397
14 changed files with 320 additions and 112 deletions

View File

@ -14,6 +14,7 @@ namespace QRBee.Droid
{
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);

View File

@ -67,6 +67,9 @@
<PackageReference Include="ZXing.Net.Mobile">
<Version>2.4.1</Version>
</PackageReference>
<PackageReference Include="ZXing.Net.Mobile.Forms">
<Version>2.4.1</Version>
</PackageReference>
</ItemGroup>
<ItemGroup>
<Compile Include="MainActivity.cs" />
@ -106,4 +109,9 @@
</ItemGroup>
<ItemGroup />
<Import Project="$(MSBuildExtensionsPath)\Xamarin\Android\Xamarin.Android.CSharp.targets" />
<ProjectExtensions>
<VisualStudio>
<UserProperties XamarinHotReloadDebuggerTimeoutExceptionQRBeeAndroidHideInfoBar="True" />
</VisualStudio>
</ProjectExtensions>
</Project>

View File

@ -10790,6 +10790,9 @@ namespace QRBee.Droid
global::Xamarin.Forms.Platform.Resource.Xml.standalone_badge_gravity_bottom_start = global::QRBee.Droid.Resource.Xml.standalone_badge_gravity_bottom_start;
global::Xamarin.Forms.Platform.Resource.Xml.standalone_badge_gravity_top_start = global::QRBee.Droid.Resource.Xml.standalone_badge_gravity_top_start;
global::Xamarin.Forms.Platform.Resource.Xml.standalone_badge_offset = global::QRBee.Droid.Resource.Xml.standalone_badge_offset;
global::ZXing.Net.Mobile.Forms.Android.Resource.Layout.zxingscanneractivitylayout = global::QRBee.Droid.Resource.Layout.zxingscanneractivitylayout;
global::ZXing.Net.Mobile.Forms.Android.Resource.Layout.zxingscannerfragmentlayout = global::QRBee.Droid.Resource.Layout.zxingscannerfragmentlayout;
global::ZXing.Net.Mobile.Forms.Android.Resource.String.library_name = global::QRBee.Droid.Resource.String.library_name;
global::ZXing.Mobile.Resource.Id.contentFrame = global::QRBee.Droid.Resource.Id.contentFrame;
global::ZXing.Mobile.Resource.Layout.zxingscanneractivitylayout = global::QRBee.Droid.Resource.Layout.zxingscanneractivitylayout;
global::ZXing.Mobile.Resource.Layout.zxingscannerfragmentlayout = global::QRBee.Droid.Resource.Layout.zxingscannerfragmentlayout;
@ -18984,214 +18987,217 @@ namespace QRBee.Droid
public const int item_view_role_description = 2131623983;
// aapt resource value: 0x7F0E0030
public const int material_clock_display_divider = 2131623984;
public const int library_name = 2131623984;
// aapt resource value: 0x7F0E0031
public const int material_clock_toggle_content_description = 2131623985;
public const int material_clock_display_divider = 2131623985;
// aapt resource value: 0x7F0E0032
public const int material_hour_selection = 2131623986;
public const int material_clock_toggle_content_description = 2131623986;
// aapt resource value: 0x7F0E0033
public const int material_hour_suffix = 2131623987;
public const int material_hour_selection = 2131623987;
// aapt resource value: 0x7F0E0034
public const int material_minute_selection = 2131623988;
public const int material_hour_suffix = 2131623988;
// aapt resource value: 0x7F0E0035
public const int material_minute_suffix = 2131623989;
public const int material_minute_selection = 2131623989;
// aapt resource value: 0x7F0E0036
public const int material_motion_easing_accelerated = 2131623990;
public const int material_minute_suffix = 2131623990;
// aapt resource value: 0x7F0E0037
public const int material_motion_easing_decelerated = 2131623991;
public const int material_motion_easing_accelerated = 2131623991;
// aapt resource value: 0x7F0E0038
public const int material_motion_easing_emphasized = 2131623992;
public const int material_motion_easing_decelerated = 2131623992;
// aapt resource value: 0x7F0E0039
public const int material_motion_easing_linear = 2131623993;
public const int material_motion_easing_emphasized = 2131623993;
// aapt resource value: 0x7F0E003A
public const int material_motion_easing_standard = 2131623994;
public const int material_motion_easing_linear = 2131623994;
// aapt resource value: 0x7F0E003B
public const int material_slider_range_end = 2131623995;
public const int material_motion_easing_standard = 2131623995;
// aapt resource value: 0x7F0E003C
public const int material_slider_range_start = 2131623996;
public const int material_slider_range_end = 2131623996;
// aapt resource value: 0x7F0E003D
public const int material_timepicker_am = 2131623997;
public const int material_slider_range_start = 2131623997;
// aapt resource value: 0x7F0E003E
public const int material_timepicker_clock_mode_description = 2131623998;
public const int material_timepicker_am = 2131623998;
// aapt resource value: 0x7F0E003F
public const int material_timepicker_hour = 2131623999;
public const int material_timepicker_clock_mode_description = 2131623999;
// aapt resource value: 0x7F0E0040
public const int material_timepicker_minute = 2131624000;
public const int material_timepicker_hour = 2131624000;
// aapt resource value: 0x7F0E0041
public const int material_timepicker_pm = 2131624001;
public const int material_timepicker_minute = 2131624001;
// aapt resource value: 0x7F0E0042
public const int material_timepicker_select_time = 2131624002;
public const int material_timepicker_pm = 2131624002;
// aapt resource value: 0x7F0E0043
public const int material_timepicker_text_input_mode_description = 2131624003;
public const int material_timepicker_select_time = 2131624003;
// aapt resource value: 0x7F0E0044
public const int mtrl_badge_numberless_content_description = 2131624004;
public const int material_timepicker_text_input_mode_description = 2131624004;
// aapt resource value: 0x7F0E0045
public const int mtrl_chip_close_icon_content_description = 2131624005;
public const int mtrl_badge_numberless_content_description = 2131624005;
// aapt resource value: 0x7F0E0046
public const int mtrl_exceed_max_badge_number_content_description = 2131624006;
public const int mtrl_chip_close_icon_content_description = 2131624006;
// aapt resource value: 0x7F0E0047
public const int mtrl_exceed_max_badge_number_suffix = 2131624007;
public const int mtrl_exceed_max_badge_number_content_description = 2131624007;
// aapt resource value: 0x7F0E0048
public const int mtrl_picker_a11y_next_month = 2131624008;
public const int mtrl_exceed_max_badge_number_suffix = 2131624008;
// aapt resource value: 0x7F0E0049
public const int mtrl_picker_a11y_prev_month = 2131624009;
public const int mtrl_picker_a11y_next_month = 2131624009;
// aapt resource value: 0x7F0E004A
public const int mtrl_picker_announce_current_selection = 2131624010;
public const int mtrl_picker_a11y_prev_month = 2131624010;
// aapt resource value: 0x7F0E004B
public const int mtrl_picker_cancel = 2131624011;
public const int mtrl_picker_announce_current_selection = 2131624011;
// aapt resource value: 0x7F0E004C
public const int mtrl_picker_confirm = 2131624012;
public const int mtrl_picker_cancel = 2131624012;
// aapt resource value: 0x7F0E004D
public const int mtrl_picker_date_header_selected = 2131624013;
public const int mtrl_picker_confirm = 2131624013;
// aapt resource value: 0x7F0E004E
public const int mtrl_picker_date_header_title = 2131624014;
public const int mtrl_picker_date_header_selected = 2131624014;
// aapt resource value: 0x7F0E004F
public const int mtrl_picker_date_header_unselected = 2131624015;
public const int mtrl_picker_date_header_title = 2131624015;
// aapt resource value: 0x7F0E0050
public const int mtrl_picker_day_of_week_column_header = 2131624016;
public const int mtrl_picker_date_header_unselected = 2131624016;
// aapt resource value: 0x7F0E0051
public const int mtrl_picker_invalid_format = 2131624017;
public const int mtrl_picker_day_of_week_column_header = 2131624017;
// aapt resource value: 0x7F0E0052
public const int mtrl_picker_invalid_format_example = 2131624018;
public const int mtrl_picker_invalid_format = 2131624018;
// aapt resource value: 0x7F0E0053
public const int mtrl_picker_invalid_format_use = 2131624019;
public const int mtrl_picker_invalid_format_example = 2131624019;
// aapt resource value: 0x7F0E0054
public const int mtrl_picker_invalid_range = 2131624020;
public const int mtrl_picker_invalid_format_use = 2131624020;
// aapt resource value: 0x7F0E0055
public const int mtrl_picker_navigate_to_year_description = 2131624021;
public const int mtrl_picker_invalid_range = 2131624021;
// aapt resource value: 0x7F0E0056
public const int mtrl_picker_out_of_range = 2131624022;
public const int mtrl_picker_navigate_to_year_description = 2131624022;
// aapt resource value: 0x7F0E0057
public const int mtrl_picker_range_header_only_end_selected = 2131624023;
public const int mtrl_picker_out_of_range = 2131624023;
// aapt resource value: 0x7F0E0058
public const int mtrl_picker_range_header_only_start_selected = 2131624024;
public const int mtrl_picker_range_header_only_end_selected = 2131624024;
// aapt resource value: 0x7F0E0059
public const int mtrl_picker_range_header_selected = 2131624025;
public const int mtrl_picker_range_header_only_start_selected = 2131624025;
// aapt resource value: 0x7F0E005A
public const int mtrl_picker_range_header_title = 2131624026;
public const int mtrl_picker_range_header_selected = 2131624026;
// aapt resource value: 0x7F0E005B
public const int mtrl_picker_range_header_unselected = 2131624027;
public const int mtrl_picker_range_header_title = 2131624027;
// aapt resource value: 0x7F0E005C
public const int mtrl_picker_save = 2131624028;
public const int mtrl_picker_range_header_unselected = 2131624028;
// aapt resource value: 0x7F0E005D
public const int mtrl_picker_text_input_date_hint = 2131624029;
public const int mtrl_picker_save = 2131624029;
// aapt resource value: 0x7F0E005E
public const int mtrl_picker_text_input_date_range_end_hint = 2131624030;
public const int mtrl_picker_text_input_date_hint = 2131624030;
// aapt resource value: 0x7F0E005F
public const int mtrl_picker_text_input_date_range_start_hint = 2131624031;
public const int mtrl_picker_text_input_date_range_end_hint = 2131624031;
// aapt resource value: 0x7F0E0060
public const int mtrl_picker_text_input_day_abbr = 2131624032;
public const int mtrl_picker_text_input_date_range_start_hint = 2131624032;
// aapt resource value: 0x7F0E0061
public const int mtrl_picker_text_input_month_abbr = 2131624033;
public const int mtrl_picker_text_input_day_abbr = 2131624033;
// aapt resource value: 0x7F0E0062
public const int mtrl_picker_text_input_year_abbr = 2131624034;
public const int mtrl_picker_text_input_month_abbr = 2131624034;
// aapt resource value: 0x7F0E0063
public const int mtrl_picker_toggle_to_calendar_input_mode = 2131624035;
public const int mtrl_picker_text_input_year_abbr = 2131624035;
// aapt resource value: 0x7F0E0064
public const int mtrl_picker_toggle_to_day_selection = 2131624036;
public const int mtrl_picker_toggle_to_calendar_input_mode = 2131624036;
// aapt resource value: 0x7F0E0065
public const int mtrl_picker_toggle_to_text_input_mode = 2131624037;
public const int mtrl_picker_toggle_to_day_selection = 2131624037;
// aapt resource value: 0x7F0E0066
public const int mtrl_picker_toggle_to_year_selection = 2131624038;
public const int mtrl_picker_toggle_to_text_input_mode = 2131624038;
// aapt resource value: 0x7F0E0067
public const int nav_app_bar_navigate_up_description = 2131624039;
public const int mtrl_picker_toggle_to_year_selection = 2131624039;
// aapt resource value: 0x7F0E0068
public const int nav_app_bar_open_drawer_description = 2131624040;
public const int nav_app_bar_navigate_up_description = 2131624040;
// aapt resource value: 0x7F0E0069
public const int not_set = 2131624041;
public const int nav_app_bar_open_drawer_description = 2131624041;
// aapt resource value: 0x7F0E006A
public const int overflow_tab_title = 2131624042;
public const int not_set = 2131624042;
// aapt resource value: 0x7F0E006B
public const int password_toggle_content_description = 2131624043;
public const int overflow_tab_title = 2131624043;
// aapt resource value: 0x7F0E006C
public const int path_password_eye = 2131624044;
public const int password_toggle_content_description = 2131624044;
// aapt resource value: 0x7F0E006D
public const int path_password_eye_mask_strike_through = 2131624045;
public const int path_password_eye = 2131624045;
// aapt resource value: 0x7F0E006E
public const int path_password_eye_mask_visible = 2131624046;
public const int path_password_eye_mask_strike_through = 2131624046;
// aapt resource value: 0x7F0E006F
public const int path_password_strike_through = 2131624047;
public const int path_password_eye_mask_visible = 2131624047;
// aapt resource value: 0x7F0E0070
public const int preference_copied = 2131624048;
public const int path_password_strike_through = 2131624048;
// aapt resource value: 0x7F0E0071
public const int search_menu_title = 2131624049;
public const int preference_copied = 2131624049;
// aapt resource value: 0x7F0E0072
public const int status_bar_notification_info_overflow = 2131624050;
public const int search_menu_title = 2131624050;
// aapt resource value: 0x7F0E0073
public const int summary_collapsed_preference_list = 2131624051;
public const int status_bar_notification_info_overflow = 2131624051;
// aapt resource value: 0x7F0E0074
public const int v7_preference_off = 2131624052;
public const int summary_collapsed_preference_list = 2131624052;
// aapt resource value: 0x7F0E0075
public const int v7_preference_on = 2131624053;
public const int v7_preference_off = 2131624053;
// aapt resource value: 0x7F0E0076
public const int v7_preference_on = 2131624054;
static String()
{

View File

@ -22,7 +22,8 @@ namespace QRBee.Droid.Services
};
var scanResult = await scanner.Scan(optionsCustom);
return scanResult.Text;
return scanResult != null ? scanResult.Text : "Nothing was scanned. Please try again.";
}
}
}

View File

@ -137,6 +137,9 @@
<PackageReference Include="ZXing.Net.Mobile">
<Version>2.4.1</Version>
</PackageReference>
<PackageReference Include="ZXing.Net.Mobile.Forms">
<Version>2.4.1</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildExtensionsPath)\Xamarin\iOS\Xamarin.iOS.CSharp.targets" />
<ItemGroup>

View File

@ -9,11 +9,15 @@
<PackageReference Include="Xamarin.Forms" Version="5.0.0.2244" />
<PackageReference Include="Xamarin.Essentials" Version="1.7.0" />
<PackageReference Include="ZXing.Net.Mobile" Version="2.4.1" />
<PackageReference Include="ZXing.Net.Mobile.Forms" Version="2.4.1" />
</ItemGroup>
<ItemGroup>
<Compile Update="Views\MainPage.xaml.cs">
<DependentUpon>MainPage.xaml</DependentUpon>
<Compile Update="Views\ClientPage.xaml.cs">
<DependentUpon>ClientPage.xaml</DependentUpon>
</Compile>
<Compile Update="Views\MerchantPage.xaml.cs">
<DependentUpon>MerchantPage.xaml</DependentUpon>
</Compile>
</ItemGroup>
@ -21,5 +25,11 @@
<EmbeddedResource Update="Views\MainPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Views\MerchantPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
<EmbeddedResource Update="Views\ClientPage.xaml">
<Generator>MSBuild:UpdateDesignTimeXaml</Generator>
</EmbeddedResource>
</ItemGroup>
</Project>

View File

@ -0,0 +1,73 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Text;
using QRBee.Views;
using Xamarin.Forms;
using ZXing;
using ZXing.Common;
namespace QRBee.ViewModels
{
internal class MerchantPageViewModel : BaseViewModel
{
private string _name;
private double _amount;
private string _qrCode;
public Command GenerateQrCommand { get; }
public MerchantPageViewModel()
{
GenerateQrCommand = new Command(OnGenerateQrClicked);
}
public string Name
{
get => _name;
set
{
if(_name==value)
return;
_name= value;
OnPropertyChanged(nameof(Name));
}
}
public double Amount
{
get => _amount;
set
{
if (_amount == value)
return;
_amount = value;
OnPropertyChanged(nameof(Amount));
}
}
public string QrCode
{
get => _qrCode;
set
{
// _qrCode = $"{Amount}/{Name}";
if (_qrCode == value)
return;
_qrCode = value;
OnPropertyChanged(nameof(QrCode));
}
}
public async void OnGenerateQrClicked(object obj)
{
QrCode = $"{Name}.{Amount}.{DateTime.Now}";
// Prefixing with `//` switches to a different navigation stack instead of pushing to the active one
// await Shell.Current.GoToAsync($"//{nameof(AboutPage)}");
}
}
}

View File

@ -0,0 +1,21 @@
<?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="QRBee.Views.ClientPage">
<ContentPage.Content>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<!-- <Label Text="Hello this is a test page." -->
<!-- VerticalOptions="CenterAndExpand" -->
<!-- HorizontalOptions="CenterAndExpand" /> -->
<StackLayout Orientation="Horizontal" VerticalOptions="FillAndExpand">
<Label x:Name="QrCodeScanner" VerticalOptions="FillAndExpand" Text="Text to scan"/>
</StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="End" Margin="0,0,0,10">
<Button Text="Scan me" HorizontalOptions="CenterAndExpand" BackgroundColor="Aqua" TextColor="Red" Clicked="OnScanButtonClicked"/>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>

View File

@ -0,0 +1,39 @@
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using QRBee.Services;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace QRBee.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class ClientPage : ContentPage
{
public ClientPage()
{
InitializeComponent();
}
private async void OnScanButtonClicked(object sender, EventArgs args)
{
try
{
var scanner = DependencyService.Get<IQRScanner>();
var result = await scanner.ScanQR();
if (result != null)
{
QrCodeScanner.Text = result;
}
}
catch (Exception ex)
{
throw;
}
}
}
}

View File

@ -2,7 +2,7 @@
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:d="http://xamarin.com/schemas/2014/forms/design"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" xmlns:viewmodels="clr-namespace:QRBee.ViewModels" x:DataType="viewmodels:LoginViewModel"
mc:Ignorable="d"
x:Class="QRBee.Views.LoginPage"
Shell.NavBarIsVisible="False">

View File

@ -1,15 +1,13 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
<TabbedPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:views="clr-namespace:QRBee.Views;assembly=QRBee"
x:Class="QRBee.Views.MainPage">
<ContentPage.Content>
<StackLayout>
<!-- <Label Text="Hello this is a test page." -->
<!-- VerticalOptions="CenterAndExpand" -->
<!-- HorizontalOptions="CenterAndExpand" /> -->
<Entry x:Name="QrCodeScanner" Placeholder="Text to scan"/>
<Button Text="Scan me" HorizontalOptions="Center" BackgroundColor="Aqua" TextColor="Red" Clicked="OnButtonClicked"/>
<!--Pages can be added as references or inline-->
<TabbedPage.Children>
<views:ClientPage Title="Client"/>
<views:MerchantPage Title="Merchant"/>
</TabbedPage.Children>
</StackLayout>
</ContentPage.Content>
</ContentPage>
<!-- <ContentPage Title="Merchant" /> -->
</TabbedPage>

View File

@ -1,38 +1,14 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using QRBee.Services;
using Xamarin.Forms;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace QRBee.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MainPage : ContentPage
public partial class MainPage : TabbedPage
{
public MainPage()
{
InitializeComponent();
}
private async void OnButtonClicked(object sender, EventArgs args)
{
try
{
var scanner = DependencyService.Get<IQRScanner>();
var result = await scanner.ScanQR();
if (result != null)
{
QrCodeScanner.Text = result;
}
}
catch (Exception ex)
{
throw;
}
}
}
}

View File

@ -0,0 +1,54 @@
<?xml version="1.0" encoding="utf-8" ?>
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:common="clr-namespace:ZXing.Common;assembly=zxing.portable"
xmlns:forms="clr-namespace:ZXing.Net.Mobile.Forms;assembly=ZXing.Net.Mobile.Forms"
xmlns:viewmodels="clr-namespace:QRBee.ViewModels"
x:DataType="viewmodels:MerchantPageViewModel"
x:Class="QRBee.Views.MerchantPage">
<ContentPage.Content>
<StackLayout HorizontalOptions="FillAndExpand" VerticalOptions="FillAndExpand">
<StackLayout Orientation="Vertical" VerticalOptions="FillAndExpand">
<StackLayout Orientation="Horizontal">
<Label Text="Enter your name: " Padding="5,10,0,0"/>
<Entry Placeholder="Your name" HorizontalOptions="FillAndExpand" Text="{Binding Name}"/>
</StackLayout>
<StackLayout Orientation="Horizontal">
<Label Text="Enter sum: " Padding="5,0,35,0" />
<Entry Placeholder="Amount" Keyboard="Numeric" HorizontalOptions="FillAndExpand" MaxLength="6" Text="{Binding Amount}"/>
</StackLayout>
<!-- <StackLayout Orientation="Horizontal"> -->
<!-- -->
<!-- </StackLayout> -->
<!-- -->
<!-- <StackLayout Orientation="Horizontal"> -->
<!-- -->
<!-- </StackLayout> -->
<forms:ZXingBarcodeImageView
BarcodeFormat="QR_CODE"
BarcodeValue="{Binding QrCode}"
HorizontalOptions="FillAndExpand"
VerticalOptions="FillAndExpand">
<forms:ZXingBarcodeImageView.BarcodeOptions>
<common:EncodingOptions Width="300" Height="300" />
</forms:ZXingBarcodeImageView.BarcodeOptions>
</forms:ZXingBarcodeImageView>
</StackLayout>
<StackLayout Orientation="Horizontal" VerticalOptions="End" Margin="0,0,0,10">
<Button Text="Generate QR code" HorizontalOptions="CenterAndExpand" BackgroundColor="Red" TextColor="Aqua" Command="{Binding GenerateQrCommand}"/>
</StackLayout>
</StackLayout>
</ContentPage.Content>
</ContentPage>

View File

@ -0,0 +1,18 @@
using System;
using Xamarin.Forms.Xaml;
using ZXing;
using System.Drawing;
using QRBee.ViewModels;
namespace QRBee.Views
{
[XamlCompilation(XamlCompilationOptions.Compile)]
public partial class MerchantPage
{
public MerchantPage()
{
BindingContext = new MerchantPageViewModel();
InitializeComponent();
}
}
}