I have a list picker which is displayed in my phone application page.I have created list picker in starting of class,and i am adding the list picker in the phoneApplicationPage_loaded() method.When the page is launched the first time, ,the scenario works perfectly and its navigates further to second page.When i navigate back to previous page(containing list picker),it shows Invalid Operation Exception occured stating "Element is already the child of another element."
I want to know how to handle these scenarios?
Code is below
namespace My.Design
{
public partial class myclass : PhoneApplicationPage
{
String[] values = null;
ListPicker picker = new ListPicker();
StackPanel sp;
StackPanel mainFrame;
String statementInfo = "";
public myclass()
{
InitializeComponent();
}
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
Debug.WriteLine("Phone Application Page Loaded_>>>>>>");
List<String> source = new List<String>();
displayUI();
}
public void displayUI()
{
Debug.WriteLine("About to display UI in miniStatement");
Debug.WriteLine("<-------------Data--------->");
Debug.WriteLine(statementInfo);
Debug.WriteLine("<-------------Data--------->");
int count = VisualTreeHelper.GetChildrenCount(this);
if (count > 0)
{
for (int i = 0; i < count; i++)
{
UIElement child = (UIElement)VisualTreeHelper.GetChild(this, i);
string childTypeName = child.GetType().ToString();
Debug.WriteLine("Elements in this Child" + childTypeName);
}
}
List<String> source = new List<String>();
String[] allParams = ItemString.Split('#');
source.Add("PleaseSelect");
for (int i = 0; i < allParams.Length; i++)
{
Debug.WriteLine("All Params Length" + allParams[i]);
if (!(allParams[i].Equals("") && (!allParams[i].Equals(null))))
{
if (values != null)
{
Debug.WriteLine("Values length" + values.Length);
values[values.Length] = allParams[i];
}
else
{
Debug.WriteLine("Allparams Length" + allParams[i]);
source.Add(allParams[i]);
}
}
}
//picker = new ListPicker();
this.picker.ItemsSource = source;
mainFrame = new StackPanel();
TextBlock box = new TextBlock();
box.Text = "> DEmoClass";
box.FontSize = 40;
mainFrame.Children.Add(box);
Canvas canvas = new Canvas();
StackPanel sp = new StackPanel();
TextBlock box1 = new TextBlock();
box1.Text = "Number";
box1.HorizontalAlignment = HorizontalAlignment.Center;
box1.FontSize = 40;
SolidColorBrush scb1 = new SolidColorBrush(Colors.Black);
box1.Foreground = scb1;
sp.Children.Add(box1);
picker.Width = 400;
picker.Height = 150;
sp.Children.Add(picker);
Canvas.SetTop(sp, 150);
canvas.Children.Add(sp);
mainFrame.Children.Add(canvas);
this.ContentPanel1.Children.Add(mainFrame);
}
protected override void OnNavigatingFrom(System.Windows.Navigation.NavigatingCancelEventArgs e)
{
/*
Debug.WriteLine("OnNavigatingFrom>>>.>>MainPage");
if (sp != null)
{
sp.Children.Remove(picker);
}*/
base.OnNavigatingFrom(e);
}
}
}
If you are not intending to update the listpicker after navigating back from the second page add the following line in your Loaded event handler
private void PhoneApplicationPage_Loaded(object sender, RoutedEventArgs e)
{
this.Loaded -= PhoneApplicationPage_Loaded;
Debug.WriteLine("Phone Application Page Loaded_>>>>>>");
List<String> source = new List<String>();
displayUI();
}
i don't know why you can not use that case when app resume from tombstoned.
error happened because when you back to your page , loaded event runs again.
by the way,
Application_Activated 's argument can tell you app resumes from tombstoned or not--.
if (e.IsApplicationInstancePreserved)
{
IsTombstoning = false;
}
else
{
IsTombstoning = true;
}
I'm curious why you're creating it in code and not leaving it in XAML? Also the error is coming from the fact that you're attempting to add it twice into a location that can probably only have a single content element. What's the higher level problem you're trying to solve?
Related
I want to binding a variable to a label which as a children in a grid.
the variable changed with a timer event.pls check my code help me found out where i am wrong.I can see the label init value is 0,but it won't update when the variable do.
public class DevicePage : ContentPage
{
IDevice device;
Label testLb = new Label();
System.Timers.Timer testtimer;
Grid gridView;
byte testt { get; set; } = 0;
GetSendData communicate;
private byte _maintext;
public byte MainText
{
get
{
return _maintext;
}
set
{
_maintext = value;
OnPropertyChanged();
}
}
public DevicePage(IDevice currDevice)
{
device = currDevice;
this.Title = "Status";
testtimer = new System.Timers.Timer();
testtimer.Interval = 1000;
testtimer.Elapsed += OnTimedEvent;
testtimer.Enabled = true;
gridView = new Grid();
testLb.Text = testt.ToString();
testLb.SetBinding(Label.TextProperty, ".");
testLb.BindingContext = MainText;
gridView.Children.Add(testLb, 0, 0);
this.Content = gridView;
}
private void OnTimedEvent(object sender, System.Timers.ElapsedEventArgs e)
{
MainText += 1;
}
after I implement INotifyPropertyChanged,testLb won't update either.But I change testLb.SetBinding(Label.TextProperty, "."); testLb.BindingContext = MainText; to testLb.SetBinding(Label.TextProperty, "MainText"); testLb.BindingContext = this; It works!
I can successfully work with the badge on my tabbar if i use it straight in my ViewWillAppear function but if i create a function where i try to control it then the badge does not appear.
This is the tabbedpaged renderer where I have to the function that changes the badge.
public override void ViewWillAppear(bool animated)
{
if (TabBar == null) return;
if (TabBar.Items == null) return;
var tabs = Element as TabbedPage;
if (tabs != null)
{
for (int i = 0; i < TabBar.Items.Length; i++)
{
UpdateItem(TabBar.Items[i], tabs.Children[i].Icon);
}
}
base.ViewWillAppear(animated);
}
private void UpdateItem(UITabBarItem item, string icon)
{
TabBar.UnselectedItemTintColor = UIColor.White;
}
public void UpdateBadge ()
{
var tabs = Element as TabbedPage;
if (tabs != null)
{
Device.BeginInvokeOnMainThread(() =>
{
var tab = TabBar.Items[3];
tab.BadgeValue = "New";
tab.BadgeColor = UIColor.Red;
});
}
}
Then I have another file where I handle a pushnotification and this is where I call the UpdateBadgefunction to both push a notification and also update the badge in the app.
void IPush.SendPush()
{
var notification = new UILocalNotification();
notification.SoundName = UILocalNotification.DefaultSoundName;
UIApplication.SharedApplication.PresentLocalNotificationNow(notification);
TabbedPage_Renderer tpr = new TabbedPage_Renderer();
tpr.UpdateBadge();
}
But as stated above this does not add the badge.
If I however add...
var tab = TabBar.Items[3];
tab.BadgeValue = "New";
tab.BadgeColor = UIColor.Red;
...inside the ViewWillAppear straight away it successfully shows an iconbadge when i start the app up but the idea is to control it so i can update the badge whenever i want.
We should not use the instance of the Renderer directly.
If you want to change the UI in the platform's renderer, we can try to define a BindableProperty in the forms. Then tell the renderer do some configuration when this property changed.
Firstly, define a BindableProperty in the page which you want to change its Badge like:
public static readonly BindableProperty BadgeTextProperty = BindableProperty.Create(nameof(BadgeText), typeof(string), typeof(MainPage), "0");
public string BadgeText {
set
{
SetValue(BadgeTextProperty, value);
}
get
{
return (string)GetValue(BadgeTextProperty);
}
}
Secondly, in the renderer, we can set the badge text when this property changed like:
for (int i = 0; i < TabBar.Items.Length; i++)
{
UpdateItem(TabBar.Items[i], tabs.Children[i].Icon);
//register the property changed event
tabs.Children[i].PropertyChanged += TabbarPageRenderer_PropertyChanged;
}
private void TabbarPageRenderer_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
var page = sender as Page;
if (page == null)
return;
if (e.PropertyName == "BadgeText")
{
if (CheckValidTabIndex(page, out int tabIndex))
{
switch(tabIndex)
{
case 0:
UpdateBadge(TabBar.Items[tabIndex], (page as MainPage).BadgeText);
break;
case 1:
//Second Page, you can expand this switch depending on your tabs children
UpdateBadge(TabBar.Items[tabIndex], (page as SecondPage).BadgeText);
break;
default:
break;
}
}
return;
}
}
public bool CheckValidTabIndex(Page page, out int tabIndex)
{
tabIndex = Tabbed.Children.IndexOf(page);
return tabIndex < TabBar.Items.Length;
}
private void UpdateItem(UITabBarItem item, string icon)
{
TabBar.UnselectedItemTintColor = UIColor.White;
...//set the tabItem
}
private void UpdateBadge(UITabBarItem item, string badgeText)
{
item.BadgeValue = text;
item.BadgeColor = UIColor.Red;
}
At last, set the BadgeText in the forms when you want to update the badge.
I am trying convert PDF to grayscale(Black/White) PDF using Websupergoo ABCpdf.
I am referring
http://www.websupergoo.com/helppdfnet/source/8-abcpdf.operations/3-recoloroperation/1-methods/recolor.htm?q=recoloroperation
Doc theDoc = new Doc();
theDoc.Read(Server.MapPath("src.pdf"));
int pages = theDoc.PageCount;
MyOp.Recolor(theDoc, (WebSupergoo.ABCpdf8.Objects.Page)theDoc.ObjectSoup[theDoc.Page]); //Here problem
theDoc.Save(Server.MapPath("greyscale1.pdf"));
theDoc.Clear();
Above code works fine for single page PDf.
This Code Converts only first page of PDF
When I tried to use a loop the below error is occurring
Page Number is not the same as Page in abcPDF, so you cannot use the page number as an index into the object soup.
Try something like this instead (untested):
int pages = theDoc.PageCount;
for(int i=0; i < pages; i++)
{
theDoc.PageNumber = i;
MyOp.Recolor(theDoc, (WebSupergoo.ABCpdf8.Objects.Page)theDoc.ObjectSoup[theDoc.Page]);
}
Edit: The above apparently didn't work, but as the documentation you linked to shows, there's a method that takes a Doc object instead of a Page object. This should work if you change your MyOp.Recolor() method to this:
public class MyOp
{
public static void Recolor(Doc doc) {
RecolorOperation op = new RecolorOperation();
op.DestinationColorSpace = new ColorSpace(doc.ObjectSoup, ColorSpaceType.DeviceGray);
op.ConvertAnnotations = false;
op.ProcessingObject += Recoloring;
op.ProcessedObject += Recolored;
op.Recolor(doc);
}
}
I am not sure what you are doing (or need to do) in the Recoloring() method or Recolored() method, but that should not matter for the changes here.
Since I went crazy with converting PDF to grayscale here
c# printing through PDF drivers, print to file option will output PS instead of PDF
I found above answer (thank you) but needs to be corrected a little bit for everyone may need:
Doc theDoc = new Doc();
theDoc.Read("test.pdf");
//doc.Rendering.ColorSpace = XRendering.ColorSpaceType.Gray;
//doc.SaveOptions.
//MyOp.Recolor(theDoc, (Page)theDoc.ObjectSoup[theDoc.Page]);
int pages = theDoc.PageCount;
for (int i = 0; i < pages; i++)
{
theDoc.PageNumber = i+1; // this is because numbering is from 1 :)
MyOp.Recolor(theDoc, (Page)theDoc.ObjectSoup[theDoc.Page]);
}
theDoc.Save("out.pdf");
theDoc.Clear();
The class remains as in their example
public class MyOp
{
public static void Recolor(Doc doc, Page page)
{
RecolorOperation op = new RecolorOperation();
op.DestinationColorSpace = new ColorSpace(doc.ObjectSoup, ColorSpaceType.DeviceGray);
op.ConvertAnnotations = false;
op.ProcessingObject += Recoloring;
op.ProcessedObject += Recolored;
op.Recolor(page);
}
//public static void Recolor(Doc doc)
//{
// RecolorOperation op = new RecolorOperation();
// op.DestinationColorSpace = new ColorSpace(doc.ObjectSoup, ColorSpaceType.DeviceGray);
// op.ConvertAnnotations = false;
// op.ProcessingObject += Recoloring;
// op.ProcessedObject += Recolored;
// op.Recolor(doc);
//}
public static void Recoloring(object sender, ProcessingObjectEventArgs e)
{
PixMap pm = e.Object as PixMap;
if (pm != null)
{
ColorSpaceType cs = pm.ColorSpaceType;
if (cs == ColorSpaceType.DeviceCMYK)
e.Cancel = true;
e.Tag = cs;
}
}
public static void Recolored(object sender, ProcessedObjectEventArgs e)
{
if (e.Successful)
{
PixMap pm = e.Object as PixMap;
if (pm != null)
{
ColorSpaceType cs = (ColorSpaceType)e.Tag;
if (pm.Width > 1000)
pm.CompressJpx(30);
else if (cs == ColorSpaceType.DeviceRGB)
pm.CompressJpeg(30);
else
pm.Compress(); // Flate
}
}
}
}
Don't forget to use (not other version) and works like a charm.
using WebSupergoo.ABCpdf9.Objects;
using WebSupergoo.ABCpdf9.Operations;
I want to get all entry controls value on button click.
My code is as below - this is how I am adding dynamic control on page:
public BookSeat()
{
ScrollView scroll = new ScrollView();
StackLayout stack = new StackLayout();
int count = Convert.ToInt32(Application.Current.Properties["NoPersonEntry"]);
for (int i = 0; i < count; i++)
{
stack.Children.Add(
new StackLayout()
{
Children = {
new Label (){TextColor = Color.Blue, Text = "First Name: ", WidthRequest = 100,StyleId="FnameLabel"+i },
new Entry() {StyleId="FnameEntry"+i }
}
}
);
}
Button button = new Button
{
Text = "Save"
};
button.Clicked += OnButtonClicked;
stack.Children.Add(button);
scroll.Content = stack;
this.Content = scroll;
}
And below code is for I want to get value on button click
public void OnButtonClicked(object sender, EventArgs e)
{
// Here I want to get value
}
What you can do is to store your entries in a list so that you can access them later on.
For example :
private List<Entry> _myentries = new List<Entry>();
public BookSeat()
{
ScrollView scroll = new ScrollView();
StackLayout stack = new StackLayout();
int count = Convert.ToInt32(Application.Current.Properties["NoPersonEntry"]);
for (int i = 0; i < count; i++)
{
var entry = new Entry() {StyleId="FnameEntry"+i };
_myentries.Add(entry);
stack.Children.Add(
new StackLayout()
{
Children = {
new Label (){TextColor = Color.Blue, Text = "First Name: ", WidthRequest = 100,StyleId="FnameLabel"+i },
entry
}
}
);
}
[...]
}
Now you can do this :
public void OnButtonClicked(object sender, EventArgs e)
{
foreach(var entry in _myentries)
{
var text = entry.Text;//here we go
}
}
I am creating an application in Xamarin.I want to use Auto-Scroll feature and i am not able to do that in a proper way. I am able to scroll manually. BUt i want to display the next picture automatically without scrolling.
Kindly share your views and codes.
I have used sliders for now. But i would like to know if i can do something better.
Grid SliderGrid = new Grid ();
//SliderGrid.BackgroundColor = Color.Black;
//SliderGrid.Padding = 10;
int SlidercolumnCount = Slider.Count;
RowDefinition Sliderrow = new RowDefinition ();
SliderGrid.RowDefinitions.Add (Sliderrow);
for (int j = 0; j < SlidercolumnCount; j++) {
ColumnDefinition col = new ColumnDefinition ();
SliderGrid.ColumnDefinitions.Add (col);
}
for (int i = 0; i < SlidercolumnCount; i++) {
var vetImageCol = new Image {
HeightRequest=260,
WidthRequest=360,
BindingContext = Slider [i],
Source = Slider [i].CategoryImage,
Aspect=Aspect.AspectFill,
};
Grid.SetColumn (vetImageCol, i);
SliderGrid.Children.Add (vetImageCol);
}
var SliderContent = new ScrollView {
Orientation=ScrollOrientation.Horizontal,
HorizontalOptions=LayoutOptions.FillAndExpand,
//HeightRequest=265,
Content= SliderGrid,
};
It's ok to do it with Task commands like this one:
private async void DoSomethingAsync()
{
await Task.Delay(1000);
DoSomething();
await Task.Delay(1000);
DoSomethingelse();
}
Although it's better to do it with Task return value instead of void but you get the idea
//page view is may ui scroll view
//counter for if my image focus on last image then return on 1 img
//new PointF((float)(your image size * count),your top margin or your fram y);
int count = 0;
public async void StartTimer()
{
await Task.Delay(3000); //3 sec
count += 1;
if (count == 5)
{
count = 0;
}
var bottomOffset = new PointF((float)(UIScreen.MainScreen.Bounds.Width * count),0);
pageview.SetContentOffset(bottomOffset, animated: true);
StartTimer();
}
public override void ViewDidLoad(){
StartTimer();
}