Xamarin iOS - Navigate to next text field with return key - ios

I couldn't find anything in the Xamarin documentation about navigating to the next text field in a series of text fields on a form, only a small tutorial on removing the keyboard.
To keep things simple I am using a txtUsername(tag 1) text field and a txtPassword(tag 2) text field. When I implement the following code, it isn't transferring to Xamarin Studio. Does anyone know the way this can be done code in Xamarin Studio, or alternatively if I can transfer the code from XCode to Xamarin Studio.
I am using the following code:
- (BOOL)textFieldShouldReturn:(UITextField *)txtUsername{
NSLog(#"textFieldShouldReturn:");
if (txtUsername.tag == 1) {
UITextField *txtPassword= (UITextField *)[self.view viewWithTag:2];
[txtPassword becomeFirstResponder];
}
else {
[txtUsername resignFirstResponder];
}
return YES;
}
Thanks in advance

I think that the simplest way to do this is using the ShouldReturn method on your UITextFields with the BecomeFirstResponder method. For example, for a login form with Username and Password UITextFields, as follows (in your ViewDidLoad method):
Username = new UITextField();
Username.ReturnKeyType = UIReturnKeyType.Next;
Username.KeyboardType = UIKeyboardType.EmailAddress;
Username.ShouldReturn = (tf) =>
{
Password.BecomeFirstResponder();
return true;
};
View.Add(Username);
Password = new UITextField();
Password.SecureTextEntry = true;
Password.ReturnKeyType = UIReturnKeyType.Go;
Password.ShouldReturn = (tf) =>
{
// Do your login
return true;
};
View.Add(Password);
When you click next when the Username is active, it moves to the Password field. Clicking Go in the password field submits the form.

I wrote a generic solution for every form (not only those with 2 fields).
I´ve got a BaseViewController with these methods:
private UITextField[] formTextfields;
protected void EnableNextKeyForTextFields(UITextField[] fields)
{
formTextfields = fields;
foreach (var field in fields)
{
field.ShouldReturn += ShouldReturn;
}
}
private bool ShouldReturn(UITextField textField)
{
int index = Array.IndexOf(formTextfields, textField);
if (index > -1 && index < formTextfields.Length - 1)
{
formTextfields[index + 1].BecomeFirstResponder();
return true;
}
else if (index == formTextfields.Length - 1)
{
formTextfields[index].ResignFirstResponder();
FormFinished();
}
return false;
}
protected virtual void FormFinished()
{
// this should be implemented on viewControllers using "EnableNextKeyForTextFields"
}
Then, in your view implementation, you just need to pass all your textfields in a single array:
EnableNextKeyForTextFields(new UITextField[] { NameField, SurnameField, EmailField, PasswordField });
When the users clicks "return" when editing the last field of the array, the method "FormFinished" will be called, so you can override it in your implementation:
protected override void FormFinished()
{
(ViewModel as RegisterViewModel).Register(); // or whatever you need to do here
}
I hope this is useful for somebody

You could make use of these functions
http://iosapi.xamarin.com/?link=M%3aMonoTouch.UIKit.UIResponder.BecomeFirstResponder
BecomeFirstResponder()
and
http://iosapi.xamarin.com/?link=M%3aMonoTouch.UIKit.UIResponder.ResignFirstResponder
ResignFirstResponder()
According to the documentation you should add the textField Delegate method like this
public virtual bool ShouldReturn (UITextField textField)
{
if (txtUsername.tag == 1) {
UITextField txtPassword = (UITextField)this.view.ViewWithTag(2);
txtPassword.BecomeFirstResponder();
}
else {
txtUsername.ResignFirstResponder();
}
return true;
}

Here's a sample of how to implement in Xamarin.iOS. There may be other simpler ways to do this but I couldn't find any, and this works for me.
I subclassed UITextFieldDelegate to add a custom event handler, then created an instance of it in my view controller code, assigned a lambda expression to the custom event handler so I could access instance variables, and set this delegate instance as the Delegate on my 2 ext fields:
public class LoginTextFieldDelegate : UITextFieldDelegate
{
public EventHandler<UITextField> OnShouldReturn;
public override bool ShouldReturn(UITextField textField)
{
if (OnShouldReturn != null)
{
OnShouldReturn(this, textField);
}
return true;
}
}
Then in my view controller ViewDidLoad method:
var textDelegate = new LoginTextFieldDelegate
{
OnShouldReturn = (sender, textField) =>
{
if (textField.Tag == txtEmailAddress.Tag)
{
txtPassword.BecomeFirstResponder();
}
else if (textField.Tag == txtPassword.Tag)
{
txtPassword.ResignFirstResponder();
}
}
};
txtEmailAddress.Delegate = textDelegate;
txtPassword.Delegate = textDelegate;
Don't forget to set a distinct tag on each UITextField in code / Interface Builder!

Could be easier to use the class available here
public override void ViewDidLoad ()
{
base.ViewDidLoad ();
// Manage keyboard and tab order
new [] {
usernameField, // Tab order = 0
passwordField, // Tab order = 1
emailField // Tab order = 2
}.InitializeNavigationOnFields();
}
Just call the method passing all the text fields in the order you want them to be navigated through the keyboard.

I recently implemented a solution on a Sign In Screen that handles the question in quite a simple and precise manner.
Not sure if these properties and events existed when the question was first asked but they will help out now for anyone else who needs it.
Entry emailEntry = new Entry()
{
Keyboard = Keyboard.Email,
ReturnType = ReturnType.Next //Changes Return Button on Keyboard to 'Next'
};
emailEntry.Completed += (s, e) => passwordEntry.Focus();
The Completed event fires when the Return Key is pressed. I then set the Focus to my passwordEntry field.
Entry passwordEntry = new Entry()
{
IsPassword = true,
ReturnType = ReturnType.Go //Changes Return Button on Keyboard to 'Next'
};
passwordEntry.Completed += (s, e) => SignInClick(s, e); //SignInClick method handles the sign in functionality
The Completed event for the password entry then initiates the SignInClick method which was previously only handled by a button on the screen.

Related

Vaadin: open calendar on field focus for datefield

Vaadin widgets are simple and awesome! But they are also poorly configurable.
I need my DateField widget to open calendar on focus event. I didn't find that functionality in official Vaadin documentation. I found some 3rd party widget here, but it's compiled for Vaadin 7.7 and I use latest Vaadin (8.0.6). Also it has Joda-time 2.1 dependency which is highly undesirable in my project. So, is there any simple way to tune stock vaadin DateField widget to open it's calendar on field focus, or do I need to write my own component for that? Any help is appreciated.
As I was saying in my comment, as far as I know, currently the framework does not offer an implicit way to programmatically open the calendar popup. The same thing goes for some other components such as the grid editor, or the combo item list.
One quick workaround I can think of, is to add a javascript extension that registers focus listeners for all date fields, and clicks the button when a date field is focused. Please find below a sample.
P.S. If you only need to apply this to only some date fields, you can add IDs and pass them to the JS, where you'll do something like document.getElementById('myDateFieldId') instead of document.getElementsByClassName("v-datefield").
1) Layout with components
public class MyDateFieldComponent extends HorizontalLayout {
public MyDateFieldComponent() {
// basic setup
DateField fromDateField = new DateField("From", LocalDate.of(2011, Month.FEBRUARY, 6));
DateField toDateField = new DateField("To", LocalDate.of(2018, Month.FEBRUARY, 6));
setSpacing(true);
addComponents(fromDateField, toDateField);
// add the extension
addExtension(new CalendarFocusPopupOpenerExtension());
}
}
2) Extension - java/server side
import com.vaadin.annotations.JavaScript;
import com.vaadin.server.AbstractJavaScriptExtension;
#JavaScript("calendar-focus-popup-opener-extension.js")
public class CalendarFocusPopupOpenerExtension extends AbstractJavaScriptExtension {
public CalendarFocusPopupOpenerExtension() {
// call the bind function defined in the associated JS
callFunction("bind");
}
}
3) Extension - js/client side
window.com_example_calendar_CalendarFocusPopupOpenerExtension = function () {
this.bind = function () {
if (document.readyState === "complete") {
// if executed when document already loaded, just bind
console.log("Doc already loaded, binding");
bindToAllDateFields();
} else {
// otherwise, bind when finished loading
console.log("Doc nod loaded, binding later");
window.onload = function () {
console.log("Doc finally loaded, binding");
bindToAllDateFields();
}
}
};
function bindToAllDateFields() {
// get all the date fields to assign focus handlers to
var dateFields = document.getElementsByClassName("v-datefield");
for (var i = 0; i < dateFields.length; i++) {
addFocusListeners(dateFields[i]);
}
}
function addFocusListeners(dateField) {
// when focusing the date field, click the button
dateField.onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
// or when focusing the date field input, click the button
dateField.getElementsByTagName("input")[0].onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
}
};
4) Result
LATER UPDATE
A second approach could be to assign some IDs to your fields, and then check periodically to see when all are visible, and as soon as they are, bind the focus listeners.
1) Layout with components
public class MyDateFieldComponent extends HorizontalLayout {
public MyDateFieldComponent() {
// basic setup
DateField fromDateField = new DateField("From", LocalDate.of(2011, Month.FEBRUARY, 6));
fromDateField.setId("fromDateField"); // use id to bind
fromDateField.setVisible(false); // initially hide it
DateField toDateField = new DateField("To", LocalDate.of(2018, Month.FEBRUARY, 6));
toDateField.setId("toDateField"); // use id to bind
toDateField.setVisible(false); // initially hide it
// simulate a delay until the fields are available
Button showFieldsButton = new Button("Show fields", e -> {
fromDateField.setVisible(true);
toDateField.setVisible(true);
});
setSpacing(true);
addComponents(showFieldsButton, fromDateField, toDateField);
// add the extension
addExtension(new CalendarFocusPopupOpenerExtension(fromDateField.getId(), toDateField.getId()));
}
}
2) Extension - java/server side
#JavaScript("calendar-focus-popup-opener-extension.js")
public class CalendarFocusPopupOpenerExtension extends AbstractJavaScriptExtension {
public CalendarFocusPopupOpenerExtension(String... idsToBindTo) {
// send the arguments as an array of strings
JsonArray arguments = Json.createArray();
for (int i = 0; i < idsToBindTo.length; i++) {
arguments.set(i, idsToBindTo[i]);
}
// call the bind defined in the associated JS
callFunction("bind", arguments);
}
}
3) Extension - js/client side
window.com_example_calendar_CalendarFocusPopupOpenerExtension = function () {
var timer;
this.bind = function (idsToBindTo) {
// check every second to see if the fields are available. interval can be tweaked as required
timer = setInterval(function () {
bindWhenFieldsAreAvailable(idsToBindTo);
}, 1000);
};
function bindWhenFieldsAreAvailable(idsToBindTo) {
console.log("Looking for the following date field ids: [" + idsToBindTo + "]");
var dateFields = [];
for (var i = 0; i < idsToBindTo.length; i++) {
var dateFieldId = idsToBindTo[i];
var dateField = document.getElementById(dateFieldId);
if (!dateField) {
// field not present, wait
console.log("Date field with id [" + dateFieldId + "] not found, sleeping");
return;
} else {
// field present, add it to the list
console.log("Date field with id [" + dateFieldId + "] found, adding to binding list");
dateFields.push(dateField);
}
}
// all fields present and accounted for, bind the listeners!
clearInterval(timer);
console.log("All fields available, binding focus listeners");
bindTo(dateFields);
}
function bindTo(dateFields) {
// assign focus handlers to all date fields
for (var i = 0; i < dateFields.length; i++) {
addFocusListeners(dateFields[i]);
}
}
function addFocusListeners(dateField) {
// when focusing the date field, click the button
dateField.onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
// or when focusing the date field input, click the button
dateField.getElementsByTagName("input")[0].onfocus = function () {
dateField.getElementsByTagName("button")[0].click();
};
}
};
4) Result

UICollectionview click event for UISwitch

In the image below the UISwitches below are housed in a collection view. However, I am currently facing a problem where. If I select a switch in the top for example in Roof Structure I select the NON-SABS APPROVED PRODUCT switch when I scroll down another switch for which was not in the view has been selected.
I have followed the following steps to ascertain how man click events are being fired. I used the console to see the output when a switch is selected.
The results showed that in some instances the switch required switch is only fired as the third event and the other two events that fire are switches that are not in the users view.
To try and solve this issue I tried solve the issue by assigning a negative click event to the switch.
This has so far not worked, see the code below
The code for the Switch event
public void btnQuestionAnswer_Click(object sender, EventArgs e)
{
UITableViewRowSwitch btnQuestionAnswer = (UITableViewRowSwitch)sender;
if ((btnQuestionAnswer.section.HasValue) && (btnQuestionAnswer.row.HasValue))
{
db_QuestionAnswer questionAnswer = questionDataModel[btnQuestionAnswer.section.Value].QuestionAnswers[btnQuestionAnswer.row.Value];
//Console.Write(questionAnswer.Answer);
Console.WriteLine(questionAnswer.Answer);
if ((btnQuestionAnswer.On))
{
if (questionDataModel[btnQuestionAnswer.section.Value].ComplianceIndicator)
{
foreach (db_QuestionAnswer QA in questionDataModel[btnQuestionAnswer.section.Value].QuestionAnswers)
{
QA.isTicked = false;
}
}
questionAnswer.isTicked = true;
// ((UICollectionView)btnQuestionAnswer.relatedView).ReloadData ();
}
else
{
questionAnswer.isTicked = false;
}
}
else
{
btnQuestionAnswer.On = !btnQuestionAnswer.On;
}
var element = count.ToString();
}
public override UICollectionViewCell GetCell (UICollectionView collectionView, NSIndexPath indexPath)
{
UIView cell;
if (questionDataModel[indexPath.Section].ComplianceIndicator)
{
cell = collectionView.DequeueReusableCell (QuestionUICollectionViewDelegateDataSource.complianceQuestionCellId, indexPath);
}
else
{
cell = collectionView.DequeueReusableCell (QuestionUICollectionViewDelegateDataSource.questionCellId, indexPath);
}
int row = indexPath.Row;
UILabel lblQuestionAnswer = (UILabel)cell.ViewWithTag (1);
UITableViewRowSwitch btnQuestionAnswer = (UITableViewRowSwitch)cell.ViewWithTag (2);
btnQuestionAnswer.ValueChanged -= btnQuestionAnswer_Click;
btnQuestionAnswer.ValueChanged -= btnQuestionAnswer_Click;
btnQuestionAnswer.ValueChanged += btnQuestionAnswer_Click;
if (row < questionDataModel [indexPath.Section].QuestionAnswers.Count)
{
lblQuestionAnswer.Text = questionDataModel[indexPath.Section].QuestionAnswers[indexPath.Row].Answer;
btnQuestionAnswer.section = indexPath.Section;
btnQuestionAnswer.row = indexPath.Row;
btnQuestionAnswer.On = questionDataModel [indexPath.Section].QuestionAnswers [indexPath.Row].isTicked;
//----------------TODO----------------//
// ----
btnQuestionAnswer.ValueChanged += btnQuestionAnswer_Click;
btnQuestionAnswer.ValueChanged -= btnQuestionAnswer_Click;
//if (!btnQuestionAnswer.hasEvent)
{
btnQuestionAnswer.ValueChanged -= btnQuestionAnswer_Click;
//btnQuestionAnswer.ValueChanged -= btnQuestionAnswer_Click;
btnQuestionAnswer.ValueChanged += btnQuestionAnswer_Click;
//btnQuestionAnswer.hasEvent = true;
}
btnQuestionAnswer.relatedView = collectionView;
if (questionDataModel [indexPath.Section].isLocked)
{
btnQuestionAnswer.Enabled = false;
}
else
{
btnQuestionAnswer.Enabled = true;
}
lblQuestionAnswer.Hidden = false;
btnQuestionAnswer.Hidden = false;
}
else
{
lblQuestionAnswer.Hidden = true;
btnQuestionAnswer.Hidden = true;
}
if (controller.loggedInUser.UserType != "Inspector")
{
btnQuestionAnswer.Enabled = false;
}
return (UICollectionViewCell)cell;
}
You would most likely need to override the following methods of the UICollectionViewCell:
public override void PrepareForReuse()
{
base.PrepareForReuse();
}
public override void AwakeFromNib()
{
base.AwakeFromNib();
}
The problem you're seeing is that the collection view is correctly 'reusing' cell's that have already been loaded into memory, as such it keeps the current 'state' of the controls that are within the cells UIView. So in the prepare for reuse you need to essentially reset all of the UISwitches to their defaults. You could then use the 'AwakeFromNib' override to ensure that the cells that you want to keep the state of their switches are set accordingly. You would probably be wise to have a few bool values within the UIcollectionViewCell that keep hold of the current state of the switches and then apply them in 'AwakeFromNib'. Hope this helps.
Edit:
As it appears you are using static cells at the moment, here is a link to xamarins documentation on deriving your own custom cells from the base UICollectionViewCell. Link
This should give you the information you need to derive the class and give you access to the methods I mentioned above, allowing you a lot more control over what appears and in what state etc.

MvxRadioGroupSelectedIndexBinding

i created a RadioGroupSelectedIndexBinding from the source of MvxRadioGroupSelectedItemBinding.
It works ok, but not at viewmodel startup: the binding from viewmodel to view is called but at this time the RadioGroup has no child views. It seems they haven't been inflated yet.
This is a "bug" (or feature :p) in Mvvmcross custom inflater/binding ? Or is there something to overload in MvxAndroidTargetBinding ?
Edit: code of MvxRadioGroupSelectedIndexBinding (Index, not Item: different from MvxRadioGroupSelectedItemBinding).
public class MvxRadioGroupSelectedIndexBinding : MvxAndroidTargetBinding
{
bool stopListeningCheckChanged = false;
private int selectedIndex = -2;
public int SelectedIndex
{
get { return selectedIndex; }
set { if(value != selectedIndex) { selectedIndex = value; FireValueChanged(SelectedIndex); } }
}
public static void Register(IMvxTargetBindingFactoryRegistry registry)
{
registry.RegisterCustomBindingFactory<RadioGroup>("SelectedIndex", radioGroup => new MvxRadioGroupSelectedIndexBinding(radioGroup));
}
public MvxRadioGroupSelectedIndexBinding(RadioGroup radioGroup) : base(radioGroup)
{
if (radioGroup == null)
{
Mvx.Trace(MvxTraceLevel.Error, "RadioGroup SelectedIndex: radioGroup is null");
return;
}
radioGroup.CheckedChange += CheckedChange;
radioGroup.ChildViewAdded += RadioGroupOnChildViewAdded;
}
private void RadioGroupOnChildViewAdded(object sender, ViewGroup.ChildViewAddedEventArgs childViewAddedEventArgs)
{
var radioGroup = Target as RadioGroup;
if (selectedIndex == radioGroup.ChildCount-1)
{
stopListeningCheckChanged = true;
radioGroup.Check(radioGroup.GetChildAt(selectedIndex).Id);
stopListeningCheckChanged = false;
}
}
private void CheckedChange(object sender, RadioGroup.CheckedChangeEventArgs e)
{
if (stopListeningCheckChanged)
return;
var radioGroup = Target as RadioGroup;
var checkedId = e.CheckedId;
if (checkedId == View.NoId)
{
SelectedIndex = -1;
return;
}
for (var i = radioGroup.ChildCount - 1; i >= 0; i--)
{
if (checkedId == radioGroup.GetChildAt(i).Id)
{
SelectedIndex = i;
return;
}
}
SelectedIndex = -1;
Mvx.Trace(MvxTraceLevel.Error, "RadioGroup id not found: {0}", checkedId);
}
public override void SetValue(object index)
{
var radioGroup = Target as RadioGroup;
if (radioGroup == null)
return;
stopListeningCheckChanged = true;
selectedIndex = (int)index;
if (selectedIndex < 0 || selectedIndex >= radioGroup.ChildCount)
{
radioGroup.ClearCheck();
}
else
{
radioGroup.Check(radioGroup.GetChildAt(selectedIndex).Id);
}
stopListeningCheckChanged = false;
}
public override Type TargetType
{
get { return typeof(object); }
}
protected override void SetValueImpl(object target, object value)
{
}
public override MvxBindingMode DefaultMode
{
get { return MvxBindingMode.TwoWay; }
}
protected override void Dispose(bool isDisposing)
{
if (isDisposing)
{
var radioGroup = Target as RadioGroup;
if (radioGroup != null)
{
radioGroup.CheckedChange -= CheckedChange;
radioGroup.ChildViewAdded -= RadioGroupOnChildViewAdded;
}
}
base.Dispose(isDisposing);
}
}
And usage
<RadioGroup
android:orientation="horizontal"
local:MvxBind="SelectedIndex SelectedChoiceIndex">
<RadioButton
android:text="choice 1"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
<RadioButton
android:text="choice 2"
android:layout_width="wrap_content"
android:layout_height="wrap_content" />
</RadioGroup>
The "bug" is that when SetValue is called, the RadioGroup has no childs. I suppose the custom inflater create and binds views at the same time. In fact it should bind views only when their childs are inflated. I may be wrong though, i've not checked the source code. And it could have other bad side effects.
This is a "bug" (or feature :p) in Mvvmcross custom inflater/binding ?
Neither - I think this is simply out of scope of what the MvxRadioGroup was designed to target.
MvxRadioGroupSelectedItemBinding was a user contribution and I believe it was designed to be used exactly as shown in https://github.com/MvvmCross/MvvmCross-Tutorials/pull/8:
<MvxRadioGroup
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:textSize="40dp"
local:MvxItemTemplate="#layout/item_radio"
local:MvxBind="ItemsSource Items;SelectedItem SelectedItem"
/>
=> so it is designed to work for lists of items where the ItemsSource is first set, and then the SelectedItem is also set.
I don't believe the author of that MvxRadioGroup had any intention of supporting AXML based lists of radio choices.
With that said, if anyone wants to author a more extensive RadioGroup solution - e.g. one that can cope with AXML defined lists or that can cope with ItemsSource changes after SelectedItem has been set, then I think this should be perfectly possible to do - and it looks like you've already gone a long way towards this :) To "perfectly" handle all combinations of dynamic and static list changes, would probably require using some kind of technique which rechecks the SelectedItem property each and every time the ItemsSource and/or static items have been added. For practical reasons I think this recheck would need to be performed within some custom RadioGroup and/or binding based code - I don't think there's any way to do this within the XML inflation handlers as Android simply doesn't present any suitable childrenInflatedAndAdded type callbacks during inflation.
It may also be interesting to note that XAML presents similar challenges in this area - e.g. see Silverlight XAML Attribute Definition Order Matters for a XAML ComboBox scenario where the items must be set before the selected item.

Close the keyboard once button pressed in Xamarin

In a view controller I have a 2 text boxes (UITextField) and a submit button. The text boxes pop up the ASCII keyboard. The Submit button takes the values from the text boxes and does something with them.
When the keyboard is open, how do I kill it once the submit button is pressed
The keyboard has a Next button, how do I get it to go to the next field.
Using Xamarin Studio 4.0.12
Thank you!
You need to do what incmiko suggested. Here's the code in C#
Part 1.
txtUsername.ShouldReturn = TextFieldShouldReturn;
txtPassword.ShouldReturn = TextFieldShouldReturn;
create a function in your view
private bool TextFieldShouldReturn(UITextField tf)
{
//change the code below as per your validation
if (tf == _txtUsername)
{
_txtPassword.BecomeFirstResponder();
return true;
}
if(tf == _txtPassword)
{
// validate field inputs as per your requirement
tf.ResignFirstResponder();
return true;
}
return true;
}
Just have a try with this ,
It's just a sample,
NSObject keyboardShowObserver;
NSObject keyboardHideObserver;
public override void ViewWillAppear(bool animated) {
base.ViewWillAppear(animated);
keyboardShowObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillShowNotification, (notification) => {
NSValue nsKeyboardBounds = (NSValue)notification.UserInfo.ObjectForKey(UIKeyboard.BoundsUserInfoKey);
RectangleF keyboardBounds = nsKeyboardBounds.RectangleFValue;
float height = View.Bounds.Height - keyboardBounds.Height;
if (NavigationController != null && NavigationController.TabBarController != null && NavigationController.TabBarController.TabBar != null) {
// Re-add tab bar height since it is hidden under keyboard but still excluded from View.Bounds.Height.
height += NavigationController.TabBarController.TabBar.Frame.Height;
}
someScrollView.Frame = new RectangleF(someScrollView.Frame.Location, new SizeF(View.Bounds.Width, height));
});
keyboardHideObserver = NSNotificationCenter.DefaultCenter.AddObserver(UIKeyboard.WillHideNotification, (notification) => {
UIApplication.EnsureUIThread();
someScrollView.Frame = new RectangleF(someScrollView.Frame.Location, View.Bounds.Size);
});
}
public override void ViewDidDisappear(bool animated) {
base.ViewDidDisappear(animated);
if (keyboardShowObserver != null) {
NSNotificationCenter.DefaultCenter.RemoveObserver(keyboardShowObserver);
}
if (keyboardHideObserver != null) {
NSNotificationCenter.DefaultCenter.RemoveObserver(keyboardHideObserver);
}
}

SqlDataSource1_Selected not working

I need to be able to change a Boolean variable if a datasource actually retrieves any data, so gridviews/detailsviews aren't displayed. I've placed all the data inside a PlaceHolder tag which is by default not visible.
But using the SqlDataSource1_Selected method, it doesn't actually change the boolean variable - why is this? Here is my code:
protected void SqlDataSource1_Selected(object sender, SqlDataSourceStatusEventArgs e)
{
if (e.AffectedRows == 0)
{
displayData = false;
}
else
{
displayData = true;
}
}
And this is a snippet from my datasource in ASP to show it is indeed linking to the method:
onselected="SqlDataSource1_Selected"
I think you are going about this the wrong way
Can you try something like this
SqlDataSource DS = new SqlDataSource();
DataView DV = new DataView();
DS.ConnectionString = _Conn_String;
DS.SelectCommand = query_String;
DataView DV = new DataView();
DV = (DataView)DS.Select(DataSourceSelectArguments.Empty);
if (DV != null)
{
//display data
}
else
{
//do not display data
}

Resources