Bind an AutoCompleteTextView to an Array of Objects (ID,NAME) - c#

I've been trying for a while to create an AutoCompleteTextView where you can search for a name, when you select a name from the list the controller should store somewhere (in my test it would be fine to just Toast.MakeTest().Show() the result).
Here's my code:
List<Persona> personeList = getPersone ();
View view = inflater.Inflate(Resource.Layout.MyFragment, container, false);
var autoCompleteSearchName = view.FindViewById<AutoCompleteTextView> (Resource.Id.autoTextName);
ArrayAdapter<Persona> autoCompleteAdapter = new ArrayAdapter<Persona> (
view.Context,
Android.Resource.Layout.SimpleDropDownItem1Line,
personeList
);
autoCompleteSearchName.Adapter = autoCompleteAdapter;
This is the part where I bind the xml element to the controller, then I create the Adapter (Persona is an Object with properties int id and String name, exposing a ToString() method).
It works fine, I can start writing a letter and it shows the suggested names.
Now I would like to get the property id bound to the name that the user selects.
Is it possible?
The only alternative I know is using spinners, but I would like to show thousands of names so I would avoid the spinner if I can.
If you see any other solution I would really appreciate since I'm quite new to Xamarin.
Thanks a lot.
EDIT. I added the autoCompleteSearchName.ItemClick += autoTextViewItemClick;
This triggers when I select an option, the problem is that e.Position is relative to the display order, and is not bound in any way to my real Object,'s properties.
Am I missing something?

You will have to create a custom adapter and use e.Id instead of e.Position. Don't forget to implement Filter in you adapter.
Note: you won't be able to subclass ArrayAdapter because you can't access the items list or override GetItemId.

Related

How to display access model/viewmodel's fields programmatically in View in ASP.NET MVC

Background
My ASP.NET MVC application allows users to create custom reports and select things like fields to display, order of fields etc. A View should be able to read those custom report configurations and display the model fields accordingly.
Example
1) Let's say we have a model called Person - Id, Name, Age, Address, Height.
2) Let's say the custom report configuration is in a model called CustomReportConfig - Shows only Age, Name and height (in that order).
Now, what should happen in the View is something like (assuming there exists a ViewModel that contains both Person and CustomReportConfig)
foreach(string fieldName in #model.ViewModel.CustomReportConfig)
#model.ViewModel.Person.**fieldName**
As you notice, the fieldName part in the above code is a string variable but in Views this should be statically typed.
Question
Is it possible to use a variable for the fieldName part in #model.Person.fieldName in the above code?
Note: I understand that this can be done by if else conditions for each field or reflection or creating a generic DataTable type of object in ViewModel etc but I'm wondering it there's a better way to do it by just creating the the fieldName in #model.Person.fieldName programmatically.
Perhaps keep a list of fields / property names, and use reflection to grab the property?
Probably a neater way to do it would be to keep a list of objects that each implement some interface, and then just loop over the list.
foreach (IMyCustomInterface obj in #model.ViewModel.CollectionOfCustomReportConfigs)
#obj.ToRenderedString()

Correct list type for checkboxes

I need my GET Create action method to return two lists to be passed to the view. One is a dropdown list so SelectList type is fine. However, the other is to be displayed as checkboxes. Can anybody advise the correct/best list type to use?
//
// GET: /Change/Create
public ActionResult Create()
{
ViewBag.StaffID = new SelectList(db.Staff, "StaffID", "Fullname")
ViewBag.BusinessAreas = new *?* (db.BusinessArea, "BusinessArea", "BuinessAreaName");
return View();
}
You can use one of the following ways:
1.use MultiSelectList. Then you will have to use a jquery to inject checkboxes into your select list, or use a 3rd party control, because I believe MVC3 doesn't have anything built-in with checkboxes.
2. Create a loop in your view and inside your loop create checkboxes for each item. (This is a little bit more work).
Also, please try to avoid using ViewBag when possible. Strongly-typed ViewModels are much nicer and give you better maintainability and many other advantages over a ViewBag.
Create a custom class with all the property you want and use it List list = new List
Iterate in View to get all the data. Even you can create HTML Helper class and generate the same and use in your view

CollectionViewSource Sorting Dynamically

I have a Car class with various properties.
I have a static Cars collection class in which, for simplicity, I have defined a bunch of car items which I can make available in XAML via an object data provider.
I have a collection view source defined in XAML which binds successfully to my ObjectDataProvider as it should.
I have a listbox which shows the collection.
I added the sort to the CVS as recommended in all the standard tutorials and all works fine.
My Question:
Suppose I want to sort on a different field. Surely there is a way to change this without having to give the code to the customer. So I implemented a combo box.
I use the following code to load a list of properties from the Car class into the combo box but I don’t just get a list of properties. I also get their data types. I don’t want this.
Car xyz=new Car(); //Make a temp Car Object so we can get a list of properties.
//Assign this to the combobox for listing.
cbxSortPrimary.ItemsSource = xyz.GetType().GetProperties();
Result (what displays in the combo box):
System.String Model
Double Price
Int32 NoOfPrevOwners
DataType PropertyName
ect... ect...
ect... ect...
ect... ect...
My goal is to load in the property names to the combo box. Then use the selected property name to build a line of code like:
myListBox.Items.SortDescriptions.Add(new SortDescription(ComboBox.SelectedItem.ToString(), ListSortDirection.Descending));
Where the ComboBox.SelectedItem.ToString() will contain the name of the property to be sorted on.
So how do I get rid of the data type in front of the property name. I know I can do all sorts of messy loading into another list, then a bunch of string handling looking for the first space from the right and chopping everything before that. But surely there must be an easier way.
Effectively what I am looking to do is to let the user sort on a different property of the Car class (So I need to load the properties somewhere and make them available for the user to select, hence the combobox). What I am asking is that there must be an easy way to get the list of properties without all the string manipulation code, and hopefully without much reflection (unless I am already using it without knowing), as it seems like a very basic requirement.
Thanks in advance for any help!
It's not messy at all:
var properties = new List<string>();
foreach (var info in typeof(Car).GetProperties())
{
properties.Add(info.Name);
}
cbxSortPrimary.ItemsSource = properties;

Bind a grid to an anonymous LINQ result, then commit changes to DB?

I've been looking into how best to do this and wisdom would be appreciated. For read only purposes, I've been happily using LINQ and binding it to a grid. For editing purposes, I've used the LinqDataSource control, enabled the Edit/Delete operations in the process, and I have a nice editable grid bound to some or all of the table's fields.
Now I have a situation where I want to edit a few fields in table A, but there are various values in linked table B that I want to display in that grid too (no editing of those). So my query looks like the below. The fields in tblDupes (cleared, notes) are what I want to edit, but I'd like to display those tblVoucher ones.
var theDupes = from d in db.tblDupes
where d.dupeGroup == Ref
select new
{
Ref = d.dupeGroup,
InvoiceNum = d.tblVoucher.invoiceRef,
Value = d.tblVoucher.invoiceAmtDecimal,
VendorNum = d.tblVoucher.vendorID,
VendorName = d.tblVoucher.vendorName,
Cleared = d.Cleared
Notes = d.Notes
};
A similar but different question LINQDataSource - Query Multiple Tables? sent me looking at scott Guthrie's blog entry http://weblogs.asp.net/scottgu/archive/2007/09/07/linq-to-sql-part-9-using-a-custom-linq-expression-with-the-lt-asp-linqdatasource-gt-control.aspx, where he handles various events to have a LinqDataSource with a custom query across tables. This still seems aimed at explicitly designed classes though, even if the class has only a subset of the fields.
So my question is: is there an easy way to allow committing of the changes made to the anonymous collection (a changes.Submit type action), or just an easy way to 'display' fields from another table while not involving them in the updating?
EDIT: Thinking more, it doesn't have to be anonymous really. I'd be happy to define a class to contain the elements in that query, since it won't change often. But, those elements would be across two tables, even though only one needs updating. Not sure if that suggests entity framework would be more suitable - I get the feeling it wouldn't - I don't want the whole 'model' always grouping the fields in this way.
Thanks!
Taking a wild guess here, but couldn't you listen to the LINQDataSource.Updating event and perform your save there? You would, of course, have some problems with the mapping since you cannot type the object in the LinqDataSourceUpdateEventArgs.OriginalObject.
What if you create a ViewModel instead of the anonymous type. Something like DupeVoucherViewModel.
Then in the Updating event, you could cast the LinqDataSourceUpdateEventArgs.OriginalObject to the DupeVoucherViewModel object and start mapping and saving your data.
Example
Given that you create a view model (a class) that you call DupeVoucherViewModel and bind to that like so:
var theDupes = from d in db.tblDupes
where d.dupeGroup == Ref
select new DupeVoucherViewModel
{
Ref = d.dupeGroup,
InvoiceNum = d.tblVoucher.invoiceRef,
Value = d.tblVoucher.invoiceAmtDecimal,
VendorNum = d.tblVoucher.vendorID,
VendorName = d.tblVoucher.vendorName,
Cleared = d.Cleared
Notes = d.Notes
};
Then the server tag should map the updating event like so:
<asp:LinqDataSource EnableUpdate="true" OnUpdating="LinqDataSource_Updating" />
And the code behind should contain the following method:
protected void LinqDataSource_Updating(object sender, LinqDataSourceUpdateEventArgs e)
{
// originalObject contains the unchanged object
var originalObject = (DupeVoucherViewModel)e.OriginalObject;
// newObject contains the changed object
var newObject = (DupeVoucherViewModel)e.NewObject;
// Perform your save using newObject
yourDataAccessComponent.SaveSomething(newObject);
}
You might need to include some more information in the DupeVoucherViewModel such as an ID of tblDupes or something, so that you can load that and change it.
You can read more about the LinqDataSource here: http://msdn.microsoft.com/en-us/library/bb514963.aspx

Bind an object which has a property of type List<> to a repeater

I've created two classes in business layer.
the first one is called Users with id (int), pass (string) and privileges (Privilege) properties and the second one is called Privilege and has id (int) and privilegeName (string) properties.
I've a method that returns all the users, and I use a repeater (actually I bind it to a DataList to auto create the ItemTemplate for me and then use a repeater) and it works and displays all the properties well except for my List property. it generates instead something like this System.Collections.Generic.List`1[WebApplication2.Public.BLL.Users]
I want to display it in a friendly way like "User Privileges : Privi1, Privi2" but still I want to keep the layers of my application clean and structured, for example I won't store them in a database in the same table and just store them as a text and append it.
I hope to find a simple and good solution...Thanks in advance guys =)
PS : I don't want to display the object Privilege, I want to display privilege.privilegeName
When using repeaters, there are two approaches, one is the one suggested by Bugai13: to have a custom property that displays it. This is fine for certain types of nested data.
Your other option is to just have a repeater inside a repeater, and bind it appropriately (to what would be a list assigned to your main data object, depending on how you O/R Mapper works).
You can have the code for the custom display property not in the data model, but in your presentation layer somewhere (depending on your framework/design), so it's not a "bad" thing to do that. It's up to you, with whatever "feels" best.
Just create property at your Bussiness object, and bind it:
public string PrivilegiesString
{
get
{
var sb = new StringBuilder("User Privileges : ");
foreach(var item in privileges)
{
sb.AppendFormat("{0}, ",item.privilegeName);
}
return sb.ToString();
}
}

Categories