Xamarin - call fragment method from MainActivity - c#

I have a viewPager with 3 tab fragments.
The code of tabFragment1 class (Note: V4Fragment = Android.Support.V4.App.Fragment):
class tabFragment1 : V4Fragment
{
public override View OnCreateView(LayoutInflater inflater, ViewGroup container, Bundle saved)
{
var v = inflater.Inflate(Resource.Layout.tabLayout1, container, false);
// Set weather icon
ImageView iv_icon = v.FindViewById<ImageView>(Resource.Id.iv_icon);
iv_icon.SetImageResource(Resource.Drawable.ic_weather_cloudy_white_48dp);
Snackbar.Make(container, "tabFragment; onCreateView()", Snackbar.LengthLong).Show();
//UpdateContent(v);
return v;
}
public void UpdateContent(View v)
{
// Sample values to read
string locationCode = "528454";
// Mapping views
TextView tv_currentConditions = v.FindViewById<TextView>(Resource.Id.currentConditions);
TextView tv_currentTemperature = v.FindViewById<TextView>(Resource.Id.currentTemperature);
TextView tv_currentRealFeel = v.FindViewById<TextView>(Resource.Id.currentRealFeel);
TextView tv_minMaxTemperature = v.FindViewById<TextView>(Resource.Id.minMaxTemperature);
// Update view from database
tv_currentConditions.Text = Sql.ReadValue(locationCode,"currentConditions");
tv_currentTemperature.Text = Sql.ReadValue(locationCode, "currentTemperature") + "°C";
tv_currentRealFeel.Text = GetString(Resource.String.feelLike) + " " + Sql.ReadValue(locationCode, "currentRealFeel") + "°C";
tv_minMaxTemperature.Text = Sql.ReadValue(locationCode, "minTemperature") + " " + Sql.ReadValue(locationCode, "maxTemperature") + "°C";
}
}
So, I want to call UpdateContent() method from MainActivity method:
public void UpdateCurrentTab()
{
ViewPager viewPager = FindViewById<ViewPager>(Resource.Id.viewpager);
int currentItem = viewPager.CurrentItem;
Snackbar.Make(drawerLayout, "CALL TO UPDATE Tab " + currentItem, Snackbar.LengthLong).Show();
View fView = viewPager.GetChildAt(currentItem);
if (currentItem == 1) { tabFragment1.UpdateContent(fView); }
}
It works fine (cause I see I get correct itemIDs in Snackbar appearing every time I select a tab), but on the last row under if clause ...
if (currentItem == 1) { tabFragment1.UpdateContent(fView); }
... i see Visual Studio error pop-up saying, that
an object reference is required for the nonstatic field, method, or property 'tabFragment1.UpdateContent(fView)'
What is the best way to silve the problem? Thanks

public void UpdateContent(View v) is object's method not type's method. So for using it you need to create object of tabFragment1 and call it method. Or you can change declaration for UpdateContent(View v) to static UpdateContent(View v) and call it as type's method.
Changing declaration:
public static void UpdateContent(View v)
{
// Put here your code from question
}
And using:
public void UpdateCurrentTab()
{
ViewPager viewPager = FindViewById<ViewPager>(Resource.Id.viewpager);
int currentItem = viewPager.CurrentItem;
Snackbar.Make(drawerLayout, "CALL TO UPDATE Tab " + currentItem, Snackbar.LengthLong).Show();
View fView = viewPager.GetChildAt(currentItem);
if (currentItem == 1)
{
// Now it's a type's method not object's
tabFragment1.UpdateContent(fView);
}
}

Related

Inject new string into Fragment/ViewModel from MainActivity class

Working with the android studio Bottom Navigation activity template, want my HomeFragment / HomeViewModel page text to change each time the Home is accessed from the bottom navigation. When I click it the first time the text it displays should be different from the text displayed the 2nd time.
I'm able to create a variable that holds the text output, and I've created a function that should be able to update that variable but I'm unable to call it up within the MainActivity class. Any ideas?
MainActivity
class MainActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(setOf(
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications))
navView.setupWithNavController(navController)
}
HomeFragment
class HomeFragment : Fragment() {
private lateinit var homeViewModel: HomeViewModel
var chosenOutput:String = "primary output";
override fun onCreateView(
inflater: LayoutInflater,
container: ViewGroup?,
savedInstanceState: Bundle?
): View? {
//using update here crashes the app
homeViewModel =
ViewModelProvider(this).get(HomeViewModel::class.java)
val root = inflater.inflate(R.layout.fragment_home, container, false)
val textView: TextView = root.findViewById(R.id.text_home)
homeViewModel.text.observe(viewLifecycleOwner, Observer {
textView.text = chosenOutput; //changing 'chosenOutput' to 'it' means that text update must take place within HomeViewModel instead of fragment.
})
return root
}
fun update(result: String)
{
chosenOutput = result;
}
}
HomeViewModel
class HomeViewModel : ViewModel() {
var temp:String = "demo"
//constructor()
private val _text = MutableLiveData<String>().apply {
value = temp;
}
fun update(result: String) //function may be obsolete if text change can be done in fragment.
{
temp = result;
}
val text: LiveData<String> = _text
}
What is the correct way to inject a string into either the Fragment or the ViewModel from the MainActivity class I've given?
You could change your approach and store your chosenOutput variable in the MainActivity
and update it everytime you select the HomeFragment
class MainActivity : AppCompatActivity()
{
var chosenOutput = "primary output"
...
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val navView: BottomNavigationView = findViewById(R.id.nav_view)
val navController = findNavController(R.id.nav_host_fragment)
val appBarConfiguration = AppBarConfiguration(setOf(
R.id.navigation_home, R.id.navigation_dashboard, R.id.navigation_notifications))
navView.apply {
setupWithNavController(navController)
setOnNavigationItemSelectedListener { menuItem ->
when (menuItem.itemId) {
R.id.navigation_home -> {
chosenOutput = "new value" // <-- Update chosen output here
// Add this method to call the `onResume` method in the fragment
showFragment(HomeFragment.newInstance())
}
else { }
}
true
}
}
private fun showFragment(fragment: Fragment) {
supportFragmentManager.beginTransaction()
.replace(R.id.nav_host_fragment, fragment)
.addToBackStack(null)
.commit()
}
}
Then you can retrieve the updated string in your Fragment with this code.
Note that I added the companion object to avoid the creation of multiple instances of the Fragment.
class HomeFragment : Fragment()
{
companion object
{
fun newInstance() : HomeFragment
{
return HomeFragment()
}
}
override fun onResume() {
super.onResume()
val newChosenOutput = (activity as MainActivity).chosenOutput
}
}

How to access in such structure a List<Class> value of a C# Dictionary in a list position, which is a class? [closed]

Closed. This question needs details or clarity. It is not currently accepting answers.
Want to improve this question? Add details and clarify the problem by editing this post.
Closed 6 years ago.
Improve this question
I'm still a new coder, learning how I can. Must confess I tried many approaches, but still not moving forward. This code could be a bit complicated, so tried to show you how it's constructed.
I want to access the dictionary I made for a state in my State Machine state, which is an instance of a class.
I designed it so I have a state in class (player can switch states), and every state holds state name, description, bool whether there are enemies, dictionary of enemies (number and a list of races), and bool whether there are non-player characters.
Added some more code so you can have an idea of how it all runs / is structured.
Machine was working great before adding monsters, now after I press play I get the error: "NullReferenceException: Object reference not set to an instance of an object
StateController.GetTransitionsAndActions () (at Assets/_Scripts/GameRPG/StateMachines/StateController.cs:169)
StateController.Start () (at Assets/_Scripts/GameRPG/StateMachines/StateController.cs:131)"
...whis is pointing to that line in State Controller: Monobehaviour script:
Debug.Log ("monster.name: " + monster.name);
Keep in mind I only show you parts of my scripts, but should be enough to make it debug output in Unity console.
public class FunMachine : IStateMachine
{
List<FunMachineState> mStates;
FunMachineState mCurrent;
FunMachineState mExit;
List <Monster> monsterList = new List<Monster> ();
public FunMachine()
{
List <Monster> monsterList = new List<Monster> ();
MonsterManualVol1 monsterManualVol1 = new MonsterManualVol1 (monsterList);
FunMachineState entryHall = new FunMachineState("Grand Entrance", "You are standing in a grand enterance of a castle.\nThere are tables and chairs, but nothing you can interact with.", "Enter the Grand Entrance", true, new Dictionary<int, Monster> (){{7, monsterList.Find(x => x.name.Contains("orc"))}}, false);
// (...) many other similar states here
}
// Hook up doors.
entryHall.Neighbors.Add(staircase);
entryHall.Neighbors.Add(mExit);
// Add them to the collection
mStates = new List<FunMachineState>();
mStates.Add(entryHall);
// Finally set my starting point
mCurrent = entryHall;
#region IStateMachine Overrides
public override IState CurrentState
{
get { return mCurrent; }
}
public override List<FunMachineState> PossibleTransitions()
{
List<FunMachineState> transitionResult = mCurrent.Neighbors;
return transitionResult = mCurrent.Neighbors;
}
public override Dictionary<int, Monster> GetStateMonsters ()
{
Dictionary<int, Monster> result = new Dictionary<int, Monster> ();
List <Monster> monsterList = new List<Monster> ();
MonsterManualVol1 monsterManualVol1 = new MonsterManualVol1 (monsterList);
result = mCurrent.Monsters;
return result;
}
// (...) more code
}
FunMachineState:
public class FunMachineState : IState
{
string mName;
string mDescription;
string mPlayerChoiceButtonText;
bool mEnemies;
bool mNpcs;
Dictionary<int, Monster> mEnemyDictionary;
List<FunMachineState> mNeighbors = new List<FunMachineState>();
public List<FunMachineState> Neighbors { get { return mNeighbors; } }
public Dictionary <int, Monster> Monsters { get { return mEnemyDictionary; } }
public FunMachineState(string mName, string mDescription, string mPlayerChoiceButtonText, bool mEnemies, Dictionary<int, Monster> mEnemyDictionary, bool mNpcs)
{
this.mName = mName;
this.mDescription = mDescription;
this.mPlayerChoiceButtonText = mPlayerChoiceButtonText;
this.mEnemies = mEnemies;
this.mEnemyDictionary = mEnemyDictionary;
this.mNpcs = mNpcs;
}
#region IState Overrides
public override string GetName()
{
Debug.Log ("Here mName runs!");
return mName;
}
public override string GetStateDescriptionText()
{
return mDescription;
}
public override Dictionary<int, Monster> GetStateMonsters()
{
return Monsters;
}
// (...) more code
}
IStateMachine:
public abstract class IStateMachine
{
// List of all possible transitions we can make from this current state.
public abstract List<FunMachineState> PossibleTransitions();
// Get those monsters.
public abstract Dictionary<int, Monster> GetStateMonsters ();
// (...) more code
}
IState:
public abstract class IState
{
public abstract Dictionary<int, Monster> GetStateMonsters ();
// Do something
public abstract void Run();
// (...) more code
}
Now run it:
public class StateController : MonoBehaviour
{
public StateController stateController;
IStateMachine machine = GetMachine();
private static IStateMachine GetMachine()
{
IStateMachine machine = null;
machine = new FunMachine();
return machine;
}
void Start()
{
if (!machine.IsComplete())
{
Debug.Log("Currently in " + machine.CurrentState);
machine.CurrentState.Run();
Text_main_game_content.text = machine.CurrentState.GetStateDescriptionText();
GetTransitionsAndActions ();
}
public void GetTransitionsAndActions(){
Dictionary<int, Monster> monsterlisting = machine.CurrentState.GetStateMonsters();
if (monsterlisting.Values.Count > 0)
foreach (var monster in monsterlisting.Values) {
Debug.Log ("monster.name: " + monster.name);
}
}
}
// (...) more code
}
And my monster collection:
public class Monster
{
public string name, description;
public bool hostile;
public int hitPoints;
public int damage;
public int loot;
public string coin_type;
public Monster (string c_name, string c_description, bool c_hostile, int c_hitPoints, int c_damage, int c_loot, string c_coin_type)
{
name = c_name;
description = c_description;
hostile = c_hostile;
loot = c_loot;
hitPoints = c_hitPoints;
coin_type = c_coin_type;
damage = c_damage;
}
}
public class MonsterManualVol1
{
public MonsterManualVol1 (List <Monster> c_monsterList)
{
List <Monster> monsterList = new List<Monster> ();
monsterList = c_monsterList;
monsterList.Add (goblin);
monsterList.Add (orc);
}
Monster goblin = new Monster("Goblin", "Cute goblin", true, 7, 5, 28, "sz");
Monster orc = new Monster("Orc", "Pretty orc", true, 6, 6, 20, "sz");
}
I really don't know what's going on. Tried to convert that dictionary to list, didn't work too.
Oh, and this debugs properly at the start of state machine. Addition to public class FunMachine: IStateMachine:
public class FunMachine : IStateMachine
{
public override List<Monster> MonsterListDebug () {
monsterList = new List<Monster> ();
MonsterManualVol1 monsterManualVol1 = new MonsterManualVol1 (monsterList);
Debug.Log ("monsterList.Count: " + monsterList.Count);
for (int i = 0; i < monsterList.Count; i++)
{
Debug.Log ("Monster name: " + monsterList [i].name +
" Monster description: " + monsterList [i].description +
" Monster hostility: " + monsterList [i].hostile +
" Monster hit points: " + monsterList [i].hitPoints +
" Monster hit damage: " + monsterList [i].damage +
" Monster hit loot: " + monsterList [i].loot + " " + monsterList [i].coin_type);
}
return monsterList;
}
public FunMachine()
{
// (...)
//MonsterListDebug (monsterList);
MonsterListDebug ();
// (...)
}
// (...)
}
I just can't get it to debug from actual CurrentState in StateController, which runs the game properly. Debug only works from FunMachine class, like shown above. Foreach loop in StateController drops null reference, that's the only problem. Monodevelop shows no errors.
It's difficult to follow the exact flow, but my guess is that the problem lies in this part:
List <Monster> monsterList = new List<Monster> ();
public FunMachine()
{
List <Monster> monsterList = new List<Monster> ();
FunMachineState entryHall = new FunMachineState("...", "...", "...", true,
new Dictionary<int, Monster> (){{7, monsterList.Find(x => x.name.Contains("orc"))}}, false);
//...
}
Specifically, you are declaring a class variable called monsterList and another local variable with the same name inside your constructor - at that stage both lists will be empty, so when you call monsterList.Find(x => x.name.Contains("orc")) you get back NULL; your dictionary then has an item with key = 7 and value = null
You later try to loop through the dictionary entries and print the monster name and get a NullReferenceException
Edit
Ok guys... I have that problem solved. ... I looked for "orc", while it's just "Orc"... That's all.
Uh, not quite. You found one way to induce the bug. You have not solved the problem.
The solution is not:
Just type a correctly cased string
Implement a case insensitive name search
I should be able to search for "Yabadabadoo" and not get a NullReferenceException.
KMussa's answer gets to it. That Dictionary<int, Monster> should handle null values. The fix is in 2 parts:
Part 1
Don't instantiate both class-level and local variables.
I think what you meant to do in the method is: monsterlist.Clear()
Part 2
Don't allow null dictionary values
or, implement the null object pattern for the Monster class
or, guard for null when iterating the dictionary
or, implement an iterator for the "monster collection" that will not pass null values to the iterating client code.
The best way to do part 2 is to write a custom "MonsterCollection" or "MonsterDictionary" class. Then the easiest fix would be an Add() method that rejects null stuff.
If both parts are not done, the problem is not fixed.
end Edit
Easier, cleaner debugging.
Move this ...
"Monster name: " + monsterList [i].name +
" Monster description: " + monsterList [i].description +
" Monster hostility: " + monsterList [i].hostile +
" Monster hit points: " + monsterList [i].hitDice +
" Monster hit damage: " + monsterList [i].damage +
" Monster hit loot: " + monsterList [i].loot + " " + monsterList
... to Monster and override ToString. then:
for (int i = 0; i < monsterList.Count; i++)
{
Debug.Log (monsterList[i].ToString());
}
return monsterList;
... and even better, also override ToString in MonsterManualVol1 then the for loop goes away and you're left with:
Debug.Log(monsterList.ToString());
Write a ToString for StateController. Of course this will also include calling ToString for it's properties.
In fact, write ToString for all your classes and really clean up logging code.
Don't need to both initialize and set a property in the constructor:
public class FunMachine : IStateMachine
{
List <Monster> monsterList = new List<Monster> ();
public FunMachine()
{
List <Monster> monsterList = new List<Monster> ();
}
Test string parameters for null:
public Monster (string c_name, ...)
{
name = c_name; // could be null
// so:
name = c_name ?? string.Empty;
In Visual Studio, do you have Debug | Exceptions... set?

instant Search functionality to listview using edittext in xamarin android

I am trying to implement instant search functionality using edittext.I have just binded the json array response to listview and added edittext at top of listview and trying to filter or search data in listview as user starts to type in edittext below code is used.Please help me. Any kind of suggestion,guidence and help is appreciated.
MainActivity.cs
SetContentView(Resource.Layout.HomeScreen);
tableItems = new List<TableItem>();
var client = new RestClient("http://azurewebsites.net/");
var request = new RestRequest("Service/regionSearch", Method.POST);
request.RequestFormat = DataFormat.Json;
tableItems = client.Execute<List<TableItem>>(request).Data;
listView.Adapter = new HomeScreenAdapter(this, tableItems);
region = FindViewById<TextView> (Resource.Id.viewtext);
area= FindViewById<TextView> (Resource.Id.viewtext2);
_filterText = FindViewById<EditText>(Resource.Id.search);
listView = FindViewById<ListView>(Resource.Id.listView);
_filterText.TextChanged += (object sender, Android.Text.TextChangedEventArgs e) => {
// filter on text changed
var searchTerm = _filterText.Text;
};
listView.ItemClick += OnListItemClick;
}
protected void OnListItemClick(object sender, Android.Widget.AdapterView.ItemClickEventArgs e)
{
var listView = sender as ListView;
var t = tableItems[e.Position];
// var clickedTableItem = listView.Adapter[e.Position];
Android.Widget.Toast.MakeText(this, clickedTableItem.DDLValue, Android.Widget.ToastLength.Short).Show();
}
HomeScreenAdapter.cs
public class HomeScreenAdapter : BaseAdapter<TableItem> {
List<TableItem> items;
Activity context;
public HomeScreenAdapter(Activity context, List<TableItem> items)
: base()
{
this.context = context;
this.items = items;
}
public override long GetItemId(int position)
{
return position;
}
public override TableItem this[int position]
{
get { return items[position]; }
}
public override int Count
{
get { return items.Count; }
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var item = items[position];
// TableItem item = items[position];
View view = convertView;
if (view == null) // no view to re-use, create new
view = context.LayoutInflater.Inflate(Resource.Layout.CustomView, null);
view.FindViewById<TextView>(Resource.Id.Text1).Text = item.DDLValue;
view.FindViewById<TextView>(Resource.Id.Text2).Text = item.areaMsg;
return view;
}
}
It looks like you're pretty close. The last step is to use the searchTerm to filter out the results in tableItems. The easiest way to do this is to simply create a new HomeScreenAdapter with the filtered list, and set that as the ListView.Adapter. Check out this example code that implements: getting the search text, filtering all of your TableItem instances, and then giving the ListView a new Adapter.
_filterText.TextChanged += (object sender, Android.Text.TextChangedEventArgs e) => {
// filter on text changed
var searchTerm = _filterText.Text;
var updatedTableItems = tableItems.Where(
// TODO Fill in your search, for example:
tableItem => tableItem.Msg.Contains(searchTerm) ||
tableItem.DDLValue.Contains(searchTerm)
).ToList();
var filteredResultsAdapter = new HomeScreenAdapter(this, updatedTableItems);
listView.Adapter = filteredResultsAdapter;
};
Notice the TODO inside of the Where clause. I have no idea how you want to search on your TableItem but once you write your Where clause, this should do what you want.
It looks like your TableItem class is something like this (for reference):
public class TableItem {
public int Id {get; set;}
public string DDLValue {get; set;}
public string Msg {get; set;}
public int Status {get; set;}
}

UISearchController and MvvmCross

I want add search logic for my application (IOS8). I have simple MvxTableViewController and display my data by UITableViewSource. Here is:
...controller:
MvxViewFor(typeof(MainViewModel))]
partial class MainController : MvxTableViewController
{
public MainController(IntPtr handle) : base(handle) { }
public override void ViewDidLoad()
{
base.ViewDidLoad();
// make background trasnsparent page
this.View.BackgroundColor = UIColor.Clear;
this.TableView.BackgroundColor = UIColor.Clear;
this.NavigationController.NavigationBar.BarStyle = UIBarStyle.Black;
this.SetBackground ();
(this.DataContext as MainViewModel).PropertyChanged += this.ViewModelPropertyChanged;
}
private void SetBackground()
{
// set blured bg image
}
private void ViewModelPropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
{
var viewModel = this.ViewModel as MainViewModel;
if (e.PropertyName == "Title")
{
this.Title = viewModel.Title;
}
else if (e.PropertyName == "Topics")
{
var tableSource = new TopicTableViewSource(viewModel.Topics);
tableSource.TappedCommand = viewModel.NavigateToChildrenPageCommand;
this.TableView.Source = tableSource;
this.TableView.ReloadData();
}
}
I read about search in IOS and choosed UISearchController for IOS8 app. But I don't understand, how I can add this controller to my view :(
I found sample from Xamarin (TableSearch) - but they don't use UITableViewSource and I don't understand what I should do with this.
I tried add controller:
this.searchController = new UISearchController (this.searchTableController)
{
WeakDelegate = this,
DimsBackgroundDuringPresentation = false,
WeakSearchResultsUpdater = this,
};
this.searchController.SearchBar.SizeToFit ();
this.TableView.TableHeaderView = searchController.SearchBar;
this.TableView.WeakDelegate = this;
this.searchController.SearchBar.WeakDelegate = this;
what should I do in this.searchTableController? Do I need move my display logic there?
Yes. The "searchTableController" should be responsible for the presentation of search results.
Here is the test project (native, not xmarin) which help you understand.
The searchController manages a "searchBar" and "searchResultPresenter". His not need add to a view-hierarchy of the carrier controller. When user starts typing a text in the "searchBar" the "SearchController" automatically shows your SearchResultPresenter for you.
Steps:
1) Instantiate search controller with the SearchResultsPresenterController.
2) When user inputs text in the search-bar you should invoke a your own service for the search. Below a sample of code..
#pragma mark - UISearchResultsUpdating
- (void)updateSearchResultsForSearchController:(UISearchController *)searchController
{
NSString *searchString = searchController.searchBar.text;
if (searchString.length > 1)
{
// TODO - call your service for the search by string
// this may be async or sync
// When a data was found - set it to presenter
[self.searchResultPresenter dataFound:<found data>];
}
}
3) In the search presenter need to reload a table in the method "dataFound:"
- (void)dataFound:(NSArray *)searchResults
{
_searchResults = searchResults;
[self.tableView reloadData];
}
Here are some advice on how to use the UISearchController with Xamarin.iOS.
Create a new class for the results table view subclassing UITableViewSource. This is gonna be the view responsible of displaying the results. You need to make the items list of that table view public.
public List<string> SearchedItems { get; set; }
In your main UIViewController, create your UISearchController and pass your result table view as an argument. I added some extra setup.
public UISearchController SearchController { get; set; }
public override void ViewDidLoad ()
{
SearchController = new UISearchController (resultsTableController) {
WeakDelegate = this,
DimsBackgroundDuringPresentation = false,
WeakSearchResultsUpdater = this,
};
SearchController.SearchBar.SizeToFit ();
SearchController.SearchBar.WeakDelegate = this;
SearchController.HidesNavigationBarDuringPresentation = false;
DefinesPresentationContext = true;
}
The best way to add the search bar to your UI in term of user experience, in my opinion, is to add it as a NavigationItem to a NavigationBarController.
NavigationItem.TitleView = SearchController.SearchBar;
Add methods to perform the search in the main UIViewController:
[Export ("updateSearchResultsForSearchController:")]
public virtual void UpdateSearchResultsForSearchController (UISearchController searchController)
{
var tableController = (UITableViewController)searchController.SearchResultsController;
var resultsSource = (ResultsTableSource)tableController.TableView.Source;
resultsSource.SearchedItems = PerformSearch (searchController.SearchBar.Text);
tableController.TableView.ReloadData ();
}
static List<string> PerformSearch (string searchString)
{
// Return a list of elements that correspond to the search or
// parse an existing list.
}
I really hope this will help you, good luck.

Why does my UIPickerView crashing when selecting

I have created a sample on github Github link
When clicking on a row or trying to scroll in the UIPickerView it will crash and i wonder why.
// create a ActionSheet
var actionPickerSheet = new UIActionSheet("Select a Category");
actionPickerSheet.Style = UIActionSheetStyle.BlackTranslucent;
// Create UIpickerView
var catPicker = new UIPickerView(){
Model = new catPickerModel(),
AutosizesSubviews = true,
Hidden = false,
ShowSelectionIndicator = true
};
// show inside view and add the catPicker as subView
actionPickerSheet.ShowInView(View);
actionPickerSheet.AddSubview(catPicker);
// resize both views so it fits smoothly
actionPickerSheet.Frame = new RectangleF(0,100,320,500);
catPicker.Frame = new RectangleF(actionPickerSheet.Frame.X,actionPickerSheet.Frame.Y-25,actionPickerSheet.Frame.Width, 216);
And the Model
private class catPickerModel : UIPickerViewModel
{
public string[] protocolNames = new string[]
{
"Web", "Phone Call", "Google Maps", "SMS", "Email"
};
public override int GetComponentCount(UIPickerView uipv)
{
return 1;
}
public override int GetRowsInComponent( UIPickerView uipv, int comp)
{
//each component has its own count.
int rows = protocolNames.Length;
return(rows);
}
public override string GetTitle(UIPickerView uipv, int row, int comp)
{
//each component would get its own title.
return protocolNames[row];
}
public override void Selected(UIPickerView uipv, int row, int comp)
{
Console.WriteLine("selected:" + row);
}
public override float GetComponentWidth(UIPickerView uipv, int comp)
{
return 300f;
}
}
I have no idea why it keeps crashing, is it some method i am missing in the Model or am i trying to do this in the wrong way ?
Thanks
Try to make your catPicker to a private variable of the class:
namespace TextfieldUIPickerView
{
public partial class TextfieldUIPickerViewViewController : UIViewController
{
private UIPickerView catPicker;
...
Looks like the GC has collected your catPicker and disposed it.

Categories

Resources