UIBarButtonItem with Custom View - c#

I try to create a UIBarButtonItem with a custom view for a Toolbar. The view itself is displayed well, but when i click the BarButton, no action occurs. It looks like the touch event is not forwarded from the view to the UIBarButtonItem instance. I have checked the responder chain and i think it looks good. I have also searched the internet and checked the Apple documentation, but can't find any hint for my problem.
Here is my code:
g__objWeatherButton = new UIBarButtonItem[1];
UIView l__objCustomView = g__objWeatherDisplay.InfoBarButton; // Returns a reference to my custom view
UIBarButtonItem l__objButton = new UIBarButtonItem(l__objCustomView);
l__objButton.Clicked += delegate {this.WeatherButtonEvent();}; // my action handler
l__objButton.Width = 200;
l__objButton.Enabled = true;
g__objWeatherButton[0] = l__objButton;
this.Items = g__objWeatherButton; // "this" is my UIToolbar object
Can someone give me a hint where the problem is? Or a working code sample (in c# please - have found some examples in Objective-C, but apparently overlooked the crucial trick ;-)

No special trick. When you want to add a custom view to a toolbar or navigation bar, you should subscribe (and respond) to that view's events. So instead of using a UIView to hold your image, create a UIButton with UIButtonType.Custom and subscribe to that button's TouchUpInside event.
You then initialize it like you do with the UIView:
UIButton l__objCustomUIButton = UIButton.FromType(UIButtonType.Custom);
//l__objCustomUIButton.SetImage(UIImage.FromFile("your button image"), UIControlState.Normal);
l__objCustomUIButton.TouchUpInside += delegate { this.WeatherButtonEvent(); };
UIBarButtonItem l__objButton = new UIBarButtonItem(l__objCustomUIButton);
Just make sure you declare the button in the class scope.

Although the answer put me in the right direction I still had trouble displaying the button. Only after I added the following the was button display with image.
l__objCustomUIButton.Frame = new System.Drawing.RectangleF(0, 0, 40, 40);
Regards
Paul

There is an easier way and the custom button will now react like a regular toolbar button.
this.SetToolbarItems( new UIBarButtonItem[] {
new UIBarButtonItem(UIBarButtonSystemItem.Refresh, (s,e) => {
Console.WriteLine("Refresh clicked");
})
, new UIBarButtonItem(UIBarButtonSystemItem.FlexibleSpace) { Width = 50 }
, new UIBarButtonItem(UIImage.FromBundle
("wrench_support_white.png"), UIBarButtonItemStyle.Plain, (sender,args) => {
Console.WriteLine("Support clicked");
})
}, false);

Related

How to delete button border after clicking outside of Form C#?

I made a simple button, but when i click outside of win form my button getting a black border. By the way i set BorderSize to "0" and it works great while i clicking inside of my form.
this.button.FlatAppearance.BorderSize = 0;
That's how it looks like.
it seems a focus problem. Try to reset the focus when the cursor leave the control.
Add these lines of code to your forms load event.
btn.FlatStyle = FlatStyle.Flat;//You can also use the popup flat style
btn.FlatAppearance.BorderColor = btn.Parent.BackColor;
btn.FlatAppearance.BorderSize = 0;
One simple workaround is to set the FlatAppearance.BorderColor of the Button to its Parent.BackColor:
this.button1.FlatAppearance.BorderColor = this.button1.Parent.BackColor;
You could set this Property subscribing to the ParentChanged event (or overriding OnParentChanged, if it's a Custom Control) if the Control can be assigned to another parent at some point.
You can also perform the same operation in batch, using the HandleCreated event and have all the Buttons (with FlatStyle = FlatStyle.Flat) subscribe to the event in the Form's constructor:
public Form1()
{
InitializeComponent();
foreach (Button button in this.Controls.OfType<Button>().Where(btn => btn.FlatStyle == FlatStyle.Flat))
{
button.HandleCreated += (s, e) => {
button.FlatAppearance.BorderColor = button.Parent.BackColor;
};
}
}

Adding a twin tabPage to tabControl through a user command

I'm a newbie in c# and probably going to ask a very easy question, but I've not been able to find anything on the web to help.
I have a tabControl with a TabPage which is containing a TextBox object; this object, when the event "Text changed" is invoked, will perform the change of the parent tabPage's name.
The textbox where I typed "text changed by me" has a method which is managing changing the name of the tabPage:
private void textBox1_TextChanged(object sender, EventArgs e)
{
if (this.textBox1.Text != "")
this.tabControl2.SelectedTab.Text = this.textBox1.Text;
else
this.tabControl2.SelectedTab.Text = "(no name)";
}
Into the current page menu is contained a control to add a new page, which runs this method when the user click on it:
private void addNewPageToolStripMenuItem_Click(object sender, EventArgs e)
{
int numPagine;
string strPagine;
numPagine = this.tabControl2.TabCount;
strPagine = numPagine.ToString();
this.tabControl2.TabPages.Add("new page" + strPagine);
}
...and here is the output, which is expected since I'm just asking to add a new empty tabPage:
So, my question is: how can I make possible that when the user is clicking on "Add new page", rather than creating an empty new tabPage the program is rather creating a page like the first one (i.e. containing a textbox into the same position which has a method to change the text of the parent tabPage that I have just created?
Here is an example.
//..
// create the new page
TabPage tpNew = new TabPage("new page..");
// add it to the tab
this.tabControl2.TabPages.Add(tpNew);
// create one labe with text and location like label1
Label lbl = new Label();
lbl.Text = label1.Text;
lbl.Location = label1.Location;
// create a new textbox..
TextBox tbx = new TextBox();
tbx.Location = textBox1.Location;
tpNew.Controls.Add(lbl);
tpNew.Controls.Add(tbx);
// add code to the new textbox via lambda code:
tbx.TextChanged += ( (sender2, evArgs) =>
{
if (tbx.Text != "")
this.tabControl2.SelectedTab.Text = tbx.Text;
else
this.tabControl2.SelectedTab.Text = "(no name)";
} );
For more complicated layout you may want to consider creating a user control..
You also may want to create the first page with this code; the, of course with real values for text and positions!
For creating a UserControl you go to the project tag and right click Add-UserControl-UserControl and name it, maybe myTagPageUC. Then you can do layout on it like on a form. A rather good example is right here on MSDN
The problem is that is has no connection to the form, meaning you'll have to code all sorts of references to make it work..
I'm not really sure if you may not be better off writing a complete clonePage method instead. It could work like the code above, but would loop over the Controls of the template page and check on the various types to add the right controls..
It really depends on what is more complicated: the Layout or the ties between the pages and the form and its other controls..

Prev, Next and Done button on keyboard using xamarin for IOS Apps

I have an IOS App developed using Xamarin Studio.
I have an UIView which has around 10 UITextView and UITextFields, I want the Keyboard to have Prev, Next and Done button which takes me to Previous and Next UIText fields.
I searched around and I got only Objective -C examples.
Can someone please help me to achieve this using Xamarin C# class?
Thanks.
It is very easy:
the part above the kayboard is a simple UIView. So create your custom UIView with the three buttons:
UIView _topKeyboard = new UIView();
UIButton _prev = new UIButton(UIButton.Type.System);
_prev.SetTitle("Prev", UIControlState.Normal);
_prev.Frame = new RectangleF(0,0, 100,20);
_prev.TouchUpInside += (object sender, EventArgs e) => {
// Add the function of the key
};
UIButton _next = new UIButton(UIButton.Type.System);
// Set as above
UIButton _done = new UIButton(UIButton.Type.System);
// set as above
// now addit to the view
_topKeyboard.Add(_prev);
_topKeyboard.Add(_next);
_topKeyboard.Add(_done);
At the end you need to add this view to the UITextView or UITextFields that you want that it is shown with the method "InputAccessoryView":
_myTextView.InputAccessoryView = _topKeyboard
That's it! :)

Close dynamically created form with dynamic button

I'm trying to close a dynamically created form with a dynamic button (this is the simplest of my jobs, I am also adding other buttons to do other jobs but I figured this is a good place to start).
As of now I can create the form, button and the click event for that button, but I don't know what to add within the click event function to close the host of that button. I am guessing I can somehow access the buttons parent through the click function? Or maybe pass the form control as an argument in the function? Any help is appreciated!
//Create form
Snapshot snapshot = new Snapshot();
snapshot.StartPosition = FormStartPosition.CenterParent;
//Create save button
Button saveButton = new Button();
saveButton.Text = "Save Screenshot";
saveButton.Location = new Point(snapshot.Width - 100, snapshot.Height - 130);
saveButton.Click += new EventHandler(saveButton_buttonClick);
//Create exit button
Button exitButton = new Button();
exitButton.Text = "Exit";
exitButton.Location = new Point(snapshot.Width - 100, snapshot.Height - 100);
//Add all the controls and open the form
snapshot.Controls.Add(saveButton);
snapshot.Controls.Add(exitButton);
snapshot.ShowDialog();
And my click event function looks pretty much normal:
void saveButton_buttonClick(object sender, EventArgs e)
{
}
Unfortunately I don't know what to add for the function to work! Thanks in advance for any help someone can give me! I feel like this should be a straight-forward problem to solve but I haven't been able to figure it out...
While it's certainly possible to do this with a named function, it's generally simpler to just use an anonymous function in cases like this:
Snapshot snapshot = new Snapshot();
snapshot.StartPosition = FormStartPosition.CenterParent;
//Create save button
Button saveButton = new Button();
saveButton.Text = "Save Screenshot";
saveButton.Location = new Point(snapshot.Width - 100, snapshot.Height - 130);
saveButton.Click += (_,args)=>
{
SaveSnapshot();
};
//Create exit button
Button exitButton = new Button();
exitButton.Text = "Exit";
exitButton.Location = new Point(snapshot.Width - 100, snapshot.Height - 100);
exitButton.Click += (_,args)=>
{
snapshot.Close();
};
//Add all the controls and open the form
snapshot.Controls.Add(saveButton);
snapshot.Controls.Add(exitButton);
snapshot.ShowDialog();
A simple way is to use a lambda method:
Button exitButton = new Button();
exitButton.Text = "Exit";
exitButton.Click += (s, e) => { shapshot.Close(); };

How do I remove a specific panel through event handling in my FlowlayoutPanel for my Windows Form Application?

For my C# Windows Form Application, I have created a flowlayoutpanel that contains several panels. Inside the panel, I have a button "Clear" for each and every single panel.
How do I write the event handler for the code for the button "Clear" such that once I have click the button, the panel would sort of be "Removed" from the flowlayoutpanel.
This is a short part of the code of the adding of panels to the flowlayoutpanel.
nFlowPanel.Controls.Add(createNotificationPanel());
nFlowPanel.Controls.Add(createNotificationPanel());
nFlowPanel.Controls.Add(createNotificationPanel());
nFlowPanel.Controls.Add(createNotificationPanelImpt());
nFlowPanel.Controls.Add(createNotificationPanelImpt());
and this is the code for the button "Clear"
Button btnClear = new Button
{
Text = "Clear",
Name = "btnClear",
Location = new Point(416, 17)
};
p.Controls.Add(btnClear);
btnClear.Click += new EventHandler(buttonClear_Click);
So what should i write in the following method to have the effect of removing e.g. the second panel that was added in the first part of code I have written?
void buttonClear_Click(object sender, EventArgs e)
{
throw new NotImplementedException();
}
EDIT
the code for creating my panel is
var p = new Panel
{
BorderStyle = BorderStyle.FixedSingle ,
Size = new Size(506,100),
Name = "notifyPanel"
};
and the code for creating my FlowLayoutPanel is
var nFlowPanel = new FlowLayoutPanel
{
FlowDirection = FlowDirection.TopDown,
WrapContents = false,
AutoScroll = true,
Size = new Size(530, 377),
Location = new Point(13, 145)
};
and the code for my button clear is
void buttonClear_Click(object sender, EventArgs e)
{
var button = (Control)sender;
var panel = button.Parent.Controls["notifyPanel"];
panel.Dispose();
}
however it gives the error
Object reference not set to an instance of an object.
on the panel.Dispose() line.
anyone can help?
The Controls.Remove() method is very dangerous, it doesn't dispose the control. Which will live on, moved to the so-called parking window, using up both Windows and managed resources. After a bit less than 10,000 times doing this it crashes your program when Windows is no longer willing to let you create any more windows.
Call the control's Dispose() method instead. That also automatically removes the control from its container.
void buttonClear_Click(object sender, EventArgs e)
{
var panel = nFlowPanel.Controls["notifyPanel"];
panel.Dispose();
}
You can do it like this:
nFlowPanel.Controls.Remove((sender as Button).Parent);
I will suggest you to use List for this. Before adding Panels in the FlowLayoutpanel, add them in the List. Then just remove the indexed panel from the flowlayoutpanel.
Panel pnlTemp = (panel)list[index];
nFlowPanel.Controls.Remove(pnlTemp);
To get the index of the button you have to add your buttons also to your list and after clicking any button, search the button in the list and get the index of the button where it is saved in the list. If my code is unclear, let me know. but I feel your task is that complex. I am not sure but this link may be of some help.
Hope it helps.

Categories