Hi I create xamarin form project and implement MasterDetailPage it was working well without any issues in both android and ios, but i run into UWP project for windows 10 it throw the exception and app crashed. Please find my stacktrace
'System.ArgumentException' occurred in Xamarin.Forms.Platform.UAP.dll
at Windows.Foundation.Size..ctor(Double width, Double height)
at Xamarin.Forms.Platform.UWP.MasterDetailControl.get_DetailSize()
at Xamarin.Forms.Platform.UWP.MasterDetailPageRenderer.UpdateBounds()
at Xamarin.Forms.Platform.UWP.MasterDetailPageRenderer.OnIsPaneOpenChanged(DependencyObject sender, DependencyProperty dp)
at Windows.UI.Xaml.DependencyObject.SetValue(DependencyProperty dp, Object value)
at Xamarin.Forms.Platform.UWP.MasterDetailPageRenderer.UpdateIsPresented()
at Xamarin.Forms.Platform.UWP.MasterDetailPageRenderer.OnElementPropertyChanged(Object sender, PropertyChangedEventArgs e)
at System.ComponentModel.PropertyChangedEventHandler.Invoke(Object sender, PropertyChangedEventArgs e)
at Xamarin.Forms.BindableObject.OnPropertyChanged(String propertyName)
at Xamarin.Forms.Element.OnPropertyChanged(String propertyName)
at Xamarin.Forms.BindableObject.SetValueActual(BindableProperty property, BindablePropertyContext context, Object value, Boolean currentlyApplying, SetValueFlags attributes, Boolean silent)
at Xamarin.Forms.BindableObject.SetValueCore(BindableProperty property, Object value, SetValueFlags attributes, SetValuePrivateFlags privateAttributes)
at Xamarin.Forms.MasterDetailPage.UpdateMasterBehavior(MasterDetailPage page)
My code
public class MasterHomePage : MasterDetailPage, MasterHomePageLisener
{
public MasterHomePage()
{
Title = AppRex.home;
Icon = "hamburger.png";
HomePageItem[] homePageItems =
{
new HomePageItem(AppRex.home, "home_icon.png", typeof(AfterLoginHomePage)),
new HomePageItem(AppRex.changePassword, "change_password_icon.png", typeof(ChangePassword)),
new HomePageItem("Set / Change PIN", "change_pin.png", typeof(LoginPinSetUpPage)),
new HomePageItem(AppRex.customerSuppoert, "support_icon.png", typeof(CustomerSupport)),
new HomePageItem(AppRex.about, "about_icon.png", typeof(AboutPage)),
new HomePageItem(AppRex.checkUpdate, "updates_icon.png", typeof(CheckUpdatedPage)),
new HomePageItem("Tutorial", "video_icon.png", typeof(TutorialVideoPage)),
new HomePageItem(AppRex.logout, "logout_icon.png", null),
};
this.Padding = new Thickness(0, Device.OnPlatform(20, 0, 0), 0, 0);
ListView list = new ListView
{
ItemsSource = homePageItems,
ItemTemplate = new DataTemplate(() =>
{
var imageCell = new LeftMenuCell();
imageCell.SetBinding(LeftMenuCell.TitleProperty, "Name");
imageCell.SetBinding(LeftMenuCell.ImageProperty, "IconSource");
return imageCell;
}),
VerticalOptions = LayoutOptions.FillAndExpand,
};
//Left menu
this.Master = new EgnatiumFull.Views.MyContentPage
{
Title = AppRex.home,
Content = new StackLayout { Children = { new Image() { Source = App.GetLogoImg()} ,
new MyLabel{Text = AppRex.version, HorizontalTextAlignment = TextAlignment.Center},
new MyLabel{Text = App.UserName, FontSize = 24, FontAttributes= FontAttributes.Bold},
new MyLabel{Text = App.UserEmailId},
new BoxView { BackgroundColor = Color.Gray, HeightRequest = 1}, list }
}
};
this.Detail = new AfterLoginHomePage(this);
if (Device.OS == TargetPlatform.WinPhone)
{
(this.Detail as EgnatiumFull.Views.MyContentPage).Content.GestureRecognizers.Add(
new TapGestureRecognizer((view) =>
{
this.IsPresented = true;
}));
}
// Define a selected handler for the ListView.
list.ItemTapped += async(sender, args) =>
{
var homePageItem = ((HomePageItem)args.Item);
var type = homePageItem.TargetType;
if (type == null)
{
if (homePageItem.Name.Equals(AppRex.logout))
{
list.SelectedItem = null;
var resp = await DisplayAlert("","Are you sure want to Logout?","Yes", "No");
if (resp)
{
await App.UpdateLoginStatus(true);
Application.Current.MainPage = App.GetPage();
}
}
}
else {
Page page = null;
if (type.Equals(typeof(AfterLoginHomePage)))
{
page = new AfterLoginHomePage(this);
}
else if (type.Equals(typeof(AboutPage)))
{
page = new AboutPage(this);
}
else if (type.Equals(typeof(ChangePassword)))
{
page = new ChangePassword(this);
}
else if (type.Equals(typeof(LoginPinSetUpPage)))
{
page = new LoginPinSetUpPage(App.UserId, App.UserEmailId, this);
}
else if (type.Equals(typeof(TutorialVideoPage)))
{
page = new TutorialVideoPage(this);
}
else if (type.Equals(typeof(CustomerSupport)))
{
page = new CustomerSupport(this);
}
else if (type.Equals(typeof(CheckUpdatedPage)))
{
page = new CheckUpdatedPage(this);
}
page.Title = ((HomePageItem)args.Item).Name;
Detail = page;
}
// Show the detail page.
this.IsPresented = false;
((ListView)sender).SelectedItem = null;
};
// Initialize the ListView selection.
//list.SelectedItem = homePageItems[0];
}
public void HomeIconClicked()
{
this.Detail = new AfterLoginHomePage(this);
}
public void MenuIconClicked()
{
this.IsPresented = !this.IsPresented;
}
}
public interface MasterHomePageLisener
{
void MenuIconClicked();
void HomeIconClicked();
}
Related
I am looking for a clean way to create a (custom) overlay with a flashlight button for the barcode scanner using the Zxing Net Mobile NuGet package.
I already looked at some samples, but unfortunately these samples use clean Xamarin and no MvvmCross.
The code below is placed inside a custom 'ScannerService', which gets called within a MvxViewModel (ScanViewModel).
What I've got so far:
IScannerService.cs
public class ScannerService : IScannerService
{
public void Scan(Action<Result> onComplete)
{
MobileBarcodeScanner.Initialize(Xamarin.Essentials.Platform.CurrentActivity.Application);
MobileBarcodeScanner scanner = new MobileBarcodeScanner
{
TopText = "Houd uw telefoon voor de barcode.",
FlashButtonText = "Flitser",
CancelButtonText = "Stoppen",
BottomText = "Het scannen gebeurt automatisch."
};
var overlay = new ZxingOverlayView(Xamarin.Essentials.Platform.CurrentActivity.Application);
var button = new Button();
button.Clicked += (sender, e) => scanner.ToggleTorch();
overlay.AddChildrenForAccessibility(button);
scanner.UseCustomOverlay = true;
scanner.CustomOverlay = overlay;
bool result = false;
scanner.ScanContinuously((scanResult) =>
{
if (!result)
{
result = true;
scanner.Cancel();
Device.BeginInvokeOnMainThread(() => onComplete(scanResult));
}
});
}
}
The problem is that I created a Xamarin.Forms Button and that this button can't be added to the custom overlay of the 'ZxingOverlayView'.
ScanViewModel.cs
private async Task Scan()
{
if (await _mediaService.CheckPermissions().ConfigureAwait(false))
{
_scanner.Scan((result) => MvxNotifyTask.Create(() => MainThread.InvokeOnMainThreadAsync(() => HandleScan(result)), OnException));
}
}
Is there an alternative way to add the flashlight button to the custom overlay?
Edit:
As Leo suggested I used the default example of ZXing.Net.Mobile. I added the 'ZXingDefaultOverlay' to my page, but unfortunately everytime I use a ZXing component inside my page it throws the following exception:
Java.Lang.NullPointerException: 'Attempt to invoke virtual method 'android.content.res.Resources android.content.Context.getResources()' on a null object reference'
Here is my code so far:
ScanningViewModel.cs (BaseViewModel inherits from 'MvxViewModel')
public class ScanningViewModel : BaseViewModel
{
private readonly IMvxNavigationService _navigationService;
private readonly IUserDialogs _userDialogs;
ZXingScannerView ZXingScannerView;
ZXingDefaultOverlay ZXingDefaultOverlay;
private Grid _grid;
public Grid Grid
{
get => _grid;
set => SetProperty(ref _grid, value);
}
public ScanningViewModel(IMvxNavigationService navigationService, IUserDialogs userDialogs)
{
_navigationService = navigationService;
_userDialogs = userDialogs;
ZXingScannerView = new ZXingScannerView
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand,
AutomationId = "zxingScannerView"
};
ZXingScannerView.OnScanResult += (result) =>
Device.BeginInvokeOnMainThread(async () =>
{
// Stop analysis until we navigate away so we don't keep reading barcodes
ZXingScannerView.IsAnalyzing = false;
// Show an alert
await _userDialogs.AlertAsync("Scanned Barcode", result.Text, "OK");
});
ZXingDefaultOverlay = new ZXingDefaultOverlay
{
TopText = "",
BottomText = "",
ShowFlashButton = true,
AutomationId = "zxingDefaultOverlay"
};
ZXingDefaultOverlay.FlashButtonClicked += (sender, e) =>
{
ZXingScannerView.IsTorchOn = !ZXingScannerView.IsTorchOn;
};
var grid = new Grid
{
HorizontalOptions = LayoutOptions.FillAndExpand,
VerticalOptions = LayoutOptions.FillAndExpand
};
var stopButton = new Button
{
WidthRequest = 100,
HeightRequest = 50,
HorizontalOptions = LayoutOptions.Start,
VerticalOptions = LayoutOptions.End,
Text = "Disable",
Command = new Command(() => ZXingScannerView.IsScanning = false)
};
var cancelButton = new Button
{
WidthRequest = 100,
HeightRequest = 50,
HorizontalOptions = LayoutOptions.Center,
VerticalOptions = LayoutOptions.End,
Text = "Cancel",
Command = new Command(async () => await _navigationService.Close(this))
};
var startButton = new Button
{
WidthRequest = 100,
HeightRequest = 50,
HorizontalOptions = LayoutOptions.End,
VerticalOptions = LayoutOptions.End,
Text = "Enable",
Command = new Command(() => ZXingScannerView.IsScanning = true)
};
grid.Children.Add(ZXingScannerView);
grid.Children.Add(ZXingDefaultOverlay);
grid.Children.Add(startButton);
grid.Children.Add(cancelButton);
grid.Children.Add(stopButton);
// The root page of your application
Grid = grid;
}
//protected override void OnAppearing()
//{
// base.OnAppearing();
// ZXingScannerView.IsScanning = true;
//}
//protected override void OnDisappearing()
//{
// ZXingScannerView.IsScanning = false;
// base.OnDisappearing();
//}
}
ScanningPage.xaml (This is a 'MvxContentPage')
<ContentPage.Content>
<StackLayout>
<ContentView Content="{Binding Grid}"></ContentView>
</StackLayout>
</ContentPage.Content>
ScanningPage.xaml.cs
[MvxContentPagePresentation(WrapInNavigationPage = true)]
public partial class ScanningPage : MvxContentPage<ScanningViewModel>
{
public ScanningPage()
{
InitializeComponent();
}
}
Any idea why it throws this specific error?
I use version 2.4.1 of the 'ZXing.Net.Mobile' and 'ZXing.Net.Mobile.Forms' NuGet package.
I have created menu dynamically.But I don't know how to handle events of menu Item.Please Let me know if anyone have solution.Thanks in Advance.
ToolStripMenuItem master,transaction,report,exit;
private void Menu1_Load(object sender, EventArgs e)
{
master = new ToolStripMenuItem("Master");
menuStrip1.Items.Add(master);
master.DropDownItems.Add("Party Master");
master.DropDownItems.Add("Item Master");
master.DropDownItems.Add("Tax Master");
master.Click += MenuClicked;
transaction = new ToolStripMenuItem("Transaction");
menuStrip1.Items.Add(transaction);
transaction.DropDownItems.Add("Inward");
transaction.DropDownItems.Add("Inoice");
transaction.DropDownItems.Add("Daily Expense");
report = new ToolStripMenuItem("Report");
menuStrip1.Items.Add(report);
report.DropDownItems.Add("Master Report");
report.DropDownItems.Add("Transaction Report");
report.DropDownItems.Add("Daily Expense Report");
exit = new ToolStripMenuItem("Exit");
menuStrip1.Items.Add(exit);
}
private void MenuClicked(object o,EventArgs e)
{
if ((((ToolStripMenuItem)o).Text) == "Party Master")
{
Master.PartyMaster p = new Master.PartyMaster();
p.Show();
}
}`
`// Master
master.DropDownItems.
AddRange(new System.Windows.Forms.ToolStripItem[]
{
partyMaster,
itemMaster,
taxMaster
}
);
master.Name = "Master";
master.Size = new System.Drawing.Size(125, 20);
master.Text = "Master";
master.Click += new System.EventHandler(master_Click);
// Party Master
partyMaster.Name = "PartyMaster";
partyMaster.Size = new System.Drawing.Size(152, 22);
partyMaster.Text = "PartyMaster";
partyMaster.Click += new System.EventHandler(partyMaster_Click);
// Item Master
itemMaster.Name = "ItemMaster";
itemMaster.Size = new System.Drawing.Size(152, 22);
itemMaster.Text = "ItemMaster";
// Tax Master
taxMaster.Name = "TaxMaster";
taxMaster.Size = new System.Drawing.Size(152, 22);
taxMaster.Text = "TaxMaster"; //`
Or more dynamically with List and for loop.
List<ToolStripMenuItem> items = new List<ToolStripMenuItems>();
And loop to add more items to the Menu
ToolStripMenuItem item = new ToolStripMenuItem();
items.Add(item);
item.Click += new EventHandler(MenuClicked); // if you want to stick with only one function
Try add your dropdown items this way:
ToolStripItem partyMaster = new ToolStripMenuItem() { Text = "Party Master" };
partyMaster.Click += MenuClicked;
ToolStripItem itemMaster = new ToolStripMenuItem() { Text = "Item Master" };
itemMaster.Click += MenuClicked;
ToolStripItem taxMaster = new ToolStripMenuItem() { Text = "Tax Master" };
taxMaster.Click += MenuClicked;
master.DropDownItems.Add(partyMaster);
master.DropDownItems.Add(itemMaster);
master.DropDownItems.Add(taxMaster);
I have userControl(wpf)
public WebBrowserControl()
{
InitializeComponent();
_Browser = new WebBrowser();
_pipeClient = new NamedPipeClient<WebMessage>("TestPipe");
_pipeClient.ServerMessage += PipeClientOnServerMessage;
_pipeClient.Error += PipeClientOnError;
_pipeClient.Start();
InternetExplorerBrowserEmulation.SetBrowserEmulationMode();
SuppressScriptErrors(_Browser, false);
SetWebBrowserFeatures();
GridBrrw.Children.Add(_Browser);
_Browser.ObjectForScripting = new ObjectForScripting(_pipeClient);
_Browser.LoadCompleted += new LoadCompletedEventHandler(_Browser_OnLoadCompleted);
_Browser.Navigating += _Browser_OnNavigating;
var th = new Thread(ExecuteInForeground);
th.Start();
}
private void ExecuteInForeground()
{
int i = 0;
while (i<=9)
{
Thread.Sleep(1000);
_pipeClient.PushMessage(new WebMessage() {Actions = "allo"});
i++;
}
}
private void _Browser_OnNavigating(object sender, NavigatingCancelEventArgs e)
{
if (IsClick)
{
var mes = new WebMessage { Actions = "OpenUrl" };
mes.Url = e.Uri.AbsoluteUri;
_pipeClient.PushMessage(mes);
e.Cancel = false;
}
return;
e.Cancel = false;
}
private void _Browser_OnLoadCompleted(object sender, NavigationEventArgs e)
{
try
{
var br = sender as WebBrowser;
if (br?.Source != null && br.Source.AbsoluteUri != e.Uri.AbsoluteUri)
{
MessageBox.Show($"Source = {br.Source.AbsoluteUri},\r\n AbsoluteUri = {e.Uri.AbsoluteUri}");
return;
}
Document = (HTMLDocument)br.Document;
if (!string.IsNullOrEmpty(FindElement))
{
var node = HtmlNode.CreateNode(FindElement);
while (GetElement(node) == null)
{
System.Windows.Forms.Application.DoEvents();
}
}
if (WaitAjax)
{
ConnectToAjax();
return;
}
if (Sleep > 0)
{
var time = TimeSpan.FromSeconds(Sleep);
Thread.Sleep(time);
}
var mes = new WebMessage { Actions = "Load" };
mes.Title = Document.title;
mes.Url = br.Source.AbsoluteUri;
mes.Domain = br.Source.Host.Replace("http", "").Replace("http://", "").Replace("https://", "").Replace("https", "");
mes.Fovicon = $"http://www.google.com/s2/favicons?domain={mes.Domain}";
if (Document != null)
{
var htmls = Document.getElementsByTagName("html");
if (htmls != null && htmls.length > 0)
{
var html = htmls.item(0) as IHTMLElement;
mes.Html = html.outerHTML;
}
}
_pipeClient.PushMessage(mes);
}
catch (Exception ex)
{
throw ex;
}
}
Event Navigating firing, ExecuteInForeground sends messages, but LoadCompleted event is not firing. Could this be due to the settings window - Property = "ResizeMode" Value = "NoResize". What am I doing wrong?
I have a entry control added using c# to my xamarin.forms app. I also have a toolbaritem, on click of which I would like to save the data which is being entered by user.
I cannot access the text value in click event, I get this error:
Error 20 The name 'txtTest' does not exist in the current context
Here is my code sample:
public SettingsPage()
{
ToolbarItem Settings = new ToolbarItem();
Settings.Name = "Settings";
Settings.Clicked += OnClick_Settings;
Settings.Order = ToolbarItemOrder.Primaru;
ToolbarItems.Add(Settings);
loadData();
}
async public void loadData()
{
Label lblTest = new Label { Text = "Test", FontAttributes = FontAttributes.Bold };
Entry txtTest = new Entry();
StackLayout stLTest = new StackLayout
{
Padding = new Thickness(10, 0, 0, 0),
Children ={
lblTest,
txtTest
}
};
Content = stTest
}
async private void OnClick_Settings(object sender, EventArgs e)
{
var test= txtTest.Text;
}
In my OnClick_Settings, I cannot find text value.
you have txtTest in loadData() method.
you should move it out of there.
Do this
Entry txtTest;
async public void loadData()
{
Label lblTest = new Label { Text = "Test", FontAttributes = FontAttributes.Bold };
txtTest = new Entry();
StackLayout stLTest = new StackLayout
{
Padding = new Thickness(10, 0, 0, 0),
Children ={
lblTest,
txtTest
}
};
Content = stTest
}
In the page_load I'm creating dynamically the headers using data from SpGetCompanies, which is working fine. Then I'm trying to add a ListView to every dynamically created accordion pane with the data source SpSearchPublicationsTop1.
protected void Page_Load(object sender, EventArgs e)
{
if (!this.IsPostBack)
{
SQLConnection dataAccessor = new SQLConnection();
dtCompanies = dataAccessor.SpGetCompanies();
if (dtCompanies.Rows.Count > 0)
{
AccordionPane pn;
Label lblContent;
int j = 0;
for (int i = 0; i < dtCompanies.Rows.Count; i++)
{
lblHeader = new Label();
lblHeader.Text = dtCompanies.Rows[i][1].ToString();
lblContent = new Label();
lblContent.Text = "Hallo";
pn = new AccordionPane();
pn.ID = "Pane" + j;
pn.HeaderContainer.Controls.Add(lblHeader);
ListView view = new ListView();
view.LayoutTemplate = new LayoutTemplate();
view.ItemTemplate = new ItemTemplate();
//view = (ListView)FindControl("lv_result");
view.DataSource = SQLConnection.SpSearchPublicationsTop1(lblHeader.Text);
view.DataBind();
#region commented stuff
//dt2 = SQLConnection.SpSearchPublicationsTop1(lblHeader.Text);
//if (dt2.Rows.Count > 0)
//{
// //view = (ListView)FindControl("lv_result");
// //column1.Text = dt2.Rows[0][0].ToString();
// //view.Columns.Add(column1);
// //Label lblAcronym = new Label();
// //lblAcronym.Text = dt2.Rows[0][0].ToString();
// //view.DataSource = lblAcronym;
// view.DataSource = dt2;
// view.DataBind();
//}
//listView1.Columns.Add(column1);
//foreach (DataRow dr in dt2.Rows)
//{
// ListViewItem lvi = new ListViewItem(dr[0].ToString()); //1.st column in datatable, instead of 0 you can write column`s name like: ["CustomerID"]
// lvi.SubItems.Add(dr[1].ToString()); //2nd column from datatable
// view.Items.Add(lvi);
//}
//this.Controls.Add(view);
//ListView lv_result = new ListView();
////lv_result.ItemTemplate = new ItemTemplate();
//lv_result.ID = "lvpane" + i;
//lv_result.Visible = true;
//dt2 = SQLConnection.SpSearchPublicationsTop1(lblHeader.Text);
//if (dt2.Rows.Count > 0)
//{
// lv_result.DataSource = dt2;
// lv_result.DataBind();
//}
//var level2 = (ListView)FindControl("lv_result");
//level2.ItemTemplate = view.ItemTemplate;
////level2.DataSource = dt2(e.AccordionItem.DataItemIndex);
////level2.DataBind();
//dt2 = SQLConnection.SpSearchPublicationsTop1(lblHeader.Text);
//if (dt2.Rows.Count > 0)
//{
// level2.DataSource = dt2;
// level2.DataBind();
//}
#endregion
pn.ContentContainer.Controls.Add(view);
//pn.ContentContainer.Controls.Add(lblContent);
Accordion1.Panes.Add(pn);
++j;
}
}
}
}
private class LayoutTemplate : ITemplate
{
public void InstantiateIn(Control container)
{
var ol = new HtmlGenericControl("ol");
var li = new HtmlGenericControl("li") { ID = "itemPlaceholder" };
ol.Controls.Add(li);
container.Controls.Add(ol);
}
}
private class ItemTemplate : ITemplate
{
public void InstantiateIn(Control container)
{
var li = new HtmlGenericControl("li");
li.DataBinding += DataBinding;
container.Controls.Add(li);
}
public void DataBinding(object sender, EventArgs e)
{
var container = (HtmlGenericControl)sender;
var dataItem = ((ListViewDataItem)container.NamingContainer).DataItem;
container.Controls.Add(new Literal() { Text = dataItem.ToString() });
}
}
With the code above the headers from the accordion are working fine, but instead of the ListView data in the content I'm only getting: System.Data.DataRowView
What am I doing wrong?
You are missing a call to:
DataBinder.Eval(container.DataItem, "YouBindingProperty");
Example:
public void DataBinding(object sender, EventArgs e)
{
var genericControl = (HtmlGenericControl)sender;
var container = (ListViewDataItem)container.NamingContainer;
container.Controls.Add(new Literal() { Text = DataBinder.Eval(container.DataItem, "YouBindingProperty") });
}