I have vaadin table with multiple columns. One of the column is of label class
container.addContainerProperty(ID_COLUMN, Label.class, "");
and I fill it up like
referenceItem.getItemProperty(ID_COLUMN).setValue(new Label(new Integer(reference.getId()).toString()));
When I sort the table by clicking on this table, it sorts the data like
1
10
100
2
200
7
So, I tried to change the class to Integer, then it works fine, but I get the numbers with comma like
1
2
...
..
7,456
8,455
How can I have the data sorted numerically and no commas.
I was able to figure out. I used Integer as class for my column and used following
referenceTable = new Table()
{
#Override
protected String formatPropertyValue(final Object a_row_id, final Object a_col_id, final Property<?> a_property)
{
if (a_property.getType() == Integer.class && null != a_property.getValue())
{
DecimalFormat df = (DecimalFormat) DecimalFormat.getInstance(getLocale());
df.applyLocalizedPattern("#0");
return df.format(a_property.getValue());
}
return super.formatPropertyValue(a_row_id, a_col_id, a_property);
}
};
It has been a while since i have been having fun with Vaadin Table.
There are property formatters, generators etc... stuff but in this case it might be easiest just to:
container.addContainerProperty(ID_COLUMN, String.class, "");
referenceItem.getItemProperty(ID_COLUMN).setValue(""+reference.getId());
Related
I have a situation where I have a list that can be at most 4 elements.
However, if I have only 1-3 elements to put in that list, how can I fill the remainder with null values?
For example, a List<int?> of length 4 with 2 given elements, should result in:
[1,3] -> [1,3,null,null]
Here's what I'm doing, but maybe there is a better way
List.generate(4, (index) {
try {
final id = given.elementAt(index);
return id;
} catch (error) {
return null;
}
});
The simplest version would probably be:
[for (var i = 0; i < 4; i++) i < given.length ? given[i] : null]
You can use List.generate, but in this case, the function is simple enough that a list literal can do the same thing more efficiently.
(Or, as #jamesdlin says, if you want a fixed-length list, use List.generate).
A more indirect variant could be:
List<GivenType?>.filled(4, null)..setAll(0, given)
where you create a list of four nulls first, then write the given list into it. It's probably just more complicated and less efficient.
I am using BeanItemContainer for my Grid. I want to get a unique list of one of the properties. For instance, let's say my beans are as follows:
class Fun {
String game;
String rules;
String winner;
}
This would display as 3 columns in my Grid. I want to get a list of all the unique values for the game property. How would I do this? I have the same property id in multiple different bean classes, so it would be nice to get the values directly from the BeanItemContainer. I am trying to avoid building this unique list before loading the data into the Grid, since doing it that way would require me to handle it on a case by case basis.
My ultimate goal is to create a dropdown in a filter based on those unique values.
There isn't any helper for directly doing what you ask for. Instead, you'd have to do it "manually" by iterating through all items and collecting the property values to a Set which would then at the end contain all unique values.
Alternatively, if the data originates from a database, then you could maybe retrieve the unique values from there by using e.g. the DISTINCT keyword in SQL.
In case anyone is curious, this is how I applied Leif's suggestion. When they enter the dropdown, I cycle through all the item ids for the property id of the column I care about, and then fill values based on that property id. Since the same Grid can be loaded with new data, I also have to "clear" this list of item ids.
filterField.addFocusListener(focus->{
if(!(filterField.getItemIds() instanceof Collection) ||
filterField.getItemIds().isEmpty())
{
BeanItemContainer<T> container = getGridContainer();
if( container instanceof BeanItemContainer && getFilterPropertyId() instanceof Object )
{
List<T> itemIds = container.getItemIds();
Set<String> distinctValues = new HashSet<String>();
for(T itemId : itemIds)
{
Property<?> prop = container.getContainerProperty(itemId, getFilterPropertyId());
String value = null;
if( prop.getValue() instanceof String )
{
value = (String) prop.getValue();
}
if(value instanceof String && !value.trim().isEmpty())
distinctValues.add(value);
}
filterField.addItems(distinctValues);
}
}
});
Minor point: the filterField variable is using the ComboBoxMultiselect add-on for Vaadin 7. Hopefully, when I finally have time to convert to Vaadin 14+, I can do something similar there.
so I have a form with several fields which are criteria for searching in a database.
I want to formulate a query using LINQ like so:
var Coll = (from obj in table where value1 = criteria1 && value2 = criteria2...)
and so on.
My problem is, I don't want to write it using If statements to check if every field has been filled in, nor do I want to make separate methods for the various search cases (criteria 1 and criteria 5 input; criteria 2 and criteria 3 input ... etc.)
So my question is: How can I achieve this without writing an excessive amount of code? If I just write in the query with comparison, will it screw up the return values if the user inputs only SOME values?
Thanks for your help.
Yes, it will screw up.
I would go with the ifs, I don't see what's wrong with them:
var query = table;
if(criteria1 != null)
query = query.Where(x => x.Value1 == criteria1);
if(criteria2 != null)
query = query.Where(x => x.Value2 == criteria2);
If you have a lot of criteria you could use expressions, a dictionary and a loop to cut down on the repetitive code.
In an ASP.NET MVC app, chances are your user input is coming from a form which is being POSTed to your server. In that case, you can make use of strongly-typed views, using a viewmodel with [Required] on the criteria that MUST be provided. Then you wrap your method in if (ModelState.IsValid) { ... } and you've excluded all the cases where the user hasn't given you something they need.
Beyond that, if you can collect your criteria into a list, you can filter it. So, you could do something like this:
filterBy = userValues.Where(v => v != null);
var Coll = (from obj in table where filterBy.Contains(value1) select obj);
You can make this more complex by having a Dictionary (or Lookup for non-unique keys) that contains a user-entered value along with some label (an enum, perhaps) that tells you which field they're filtering by, and then you can group them by that label to separate out the filters for each field, and then filter as above. You could even have a custom SearchFilter object that contains other info, so you can have filters with AND, NOT and OR conditions...
Failing that, you can remember that until you trigger evaluation of an IQueryable, it doesn't hit the database, so you can just do this:
var Coll = (from obj in table where value1 == requiredCriteria select obj);
if(criteria1 != null)
{
query = query.Where(x => x.Value1 == criteria1);
}
//etc...
if(criteria5 != null)
{
query = query.Where(x => x.Value5 == criteria5);
}
return query.ToList();
That first line applies any criteria that MUST be there; if there aren't any mandatory ones then it could just be var Coll = table;.
That will add any criteria that are provided will be applied, any that aren't will be ignored, you catch all the possible combinations, and only one query is made at the end when you .ToList() it.
As I understand of your question you want to centralize multiple if for the sake of readability; if I were right the following would be one of some possible solutions
Func<object, object, bool> CheckValueWithAnd = (x, y) => x == null ? true : x==y;
var query = from obj in table
where CheckValue(obj.value1, criteria1) &&
CheckValue(obj.value2, criteria2) &&
...
select obj;
It ls flexible because in different situations or scenarios you can change the function in the way that fulfill your expectation and you do not need to have multiple if.
If you want to use OR operand in your expression you need to have second function
Func<object, object, bool> CheckValueWithOr = (x, y) => x == null ? false : x==y;
I have a listview that I fill from an Adapter. My original code the data was being returned from a table, but now I need to get the code from a query with a join so the examples I used will no longer work and I haven't been able to find out how to use a query for this. I'm using an ORMrepository.
In my ORMrepository I have this function
public IList<Coe> GetmyCoe()
{
using (var database = new SQLiteConnection(_helper.WritableDatabase.Path))
{
string query = "SELECT Coe.Id, Adult.LName + ', ' + Adult.MName AS Name, Coe.Createdt FROM Adult INNER JOIN Coe ON Adult.CoeMID = Coe.Id";
return database.Query<Coe>(query);
}
}
which actually returns the data I want.
then in my Activity page I have this.
_list = FindViewById<ListView>(Resource.Id.List);
FindViewById<ListView>(Resource.Id.List).ItemClick += new System.EventHandler<ItemEventArgs>(CoeList_ItemClick);
var Coe = ((OmsisMobileApplication)Application).OmsisRepository.GetmyCoe();
_list.Adapter = new CoeListAdapter(this, Coe);
My Adapter page is where I have the problem, I know it is set up to to looking at a table which I'm not doing anymore. But I don't know how to change it for what I'm passing into it now. Current CoeListAdapter is:
public class CoeListAdapter : BaseAdapter
{
private IEnumerable<Coe> _Coe;
private Activity _context;
public CoeListAdapter(Activity context, IEnumerable<Coe> Coe)
{
_context = context;
_Coe = Coe;
}
public override View GetView(int position, View convertView, ViewGroup parent)
{
var view = (convertView
?? _context.LayoutInflater.Inflate(
Resource.Layout.CoeListItem, parent, false)
) as LinearLayout;
var Coe = _Coe.ElementAt(position);
view.FindViewById<TextView>(Resource.Id.CoeMID).Text = Coe.Id.ToString();
//view.FindViewById<TextView>(Resource.Id.GrdnMaleName).Text = Coe.Name;
view.FindViewById<TextView>(Resource.Id.CreateDt).Text = Coe.CreateDt;
return view;
}
public override int Count
{
get { return _Coe.Count(); }
}
public Coe GetCoe(int position)
{
return _Coe.ElementAt(position);
}
public override Java.Lang.Object GetItem(int position)
{
return null;
}
public override long GetItemId(int position)
{
return position;
}
}
How do I set up the CoeListAdapter.cs page so that it can use the passed in data. As you can see I have a commented out lines where I fill a TextView which error because Coe.Name is not in the table model for Coe. but it is returned in the query. I believe my problem is IEnumerable but what do I change it to. I'm new to Mobile developement and suing VS2010 for Mono
The problem probably lies with the binding/mapping of the object not the creation of the view.
Or probably more specifically, the query.
Adult.LName + ', ' + Adult.MName AS Name
this should be:
Adult.LName || ', ' || Adult.MName AS Name
See also: String concatenation does not work in SQLite
From the sqlite docs: http://www.sqlite.org/lang_expr.html under the Operators heading:
The unary operator + is a no-op. It can be applied to strings,
numbers, blobs or NULL and it always returns a result with the same
value as the operand.
Note that there are two variations of the equals and not equals
operators. Equals can be either = or ==. The non-equals operator can
be either != or <>. The || operator is "concatenate" - it joins
together the two strings of its operands. The operator % outputs the
value of its left operand modulo its right operand.
The result of any binary operator is either a numeric value or NULL,
except for the || concatenation operator which always evaluates to
either NULL or a text value.
This shows that the + will evaluate to zero. If you use ||, the value will either be the correct value or NULL (if either of Adult.LName or Adult.MName is NULL).
This can be fixed by:
coalesce(first, '') || ', ' || coalesce(second, '')
but this may result in , LastName or FirstName,.
Another way would be to create another two properties in Coe called LName and MName.
Then bind the values to those properties and use the Name property like this:
public string Name
{
get { return string.Join(", ", LName, MName); }
}
This will probably be better as you can change how the Name appears especially if there are different combinations of First, Middle and Last names in different places.
And off topic:
I believe my problem is IEnumerable...
This is probably not too true as it returns the correct values. A better way would be to use IList as IEnumerable will iterate through the list each time to get the item as it does not know that the collection is actually a list. (I think)
thanks for the help on the concantination, I did find that was wrong, I did fix my problem, I was using an example by Greg Shackles on how to set up using a data base. what I had to do was create a new model with the elements I was wanting. So I created a new Model and called it CoeList, then everywhere I had List or IEnumerable I changed it to List or IEnumerable and it worked.
I'm trying to create a WebGrid which has to be very dynamic. The columns are defined in a list, which I've done like so:
#{
List<WebGridColumn> columns = new List<WebGridColumn>();
foreach (var column in Model.Columns)
{
columns.Add(new WebGridColumn() { ColumnName = column.Name, Header = column.Name });
}
}
#grid.GetHtml(
columns: columns)
All well and good, but the problem I have is with the rows. I'll try and explain...
For this question let's say we have two columns for Name and Address.
I have a collection of row objects, lets say SearchResult objects. A SearchResult contains a Dictionary of any number of attributes, such as Name, Address, Phone, Height, Bra Size, or anything (think of the EAV pattern). I need to access the attributes based on Column Name.
I figured I could do this using format, but I can't seem to figure it out. I want something like this:
columns.Add(new WebGridColumn() { ColumnName = column.Name, Header =
column.Header, Format = #<text>#item.Attributes[column.Name]</text> });
This sort of works but despite creating the format for the separate columns, the rows get populated with only the last column's format. i.e.:
Name Address
1 Main Street 1 Main Street
45 Paradise Av 45 Paradise Av
etc
I think it should work if you leave out the "ColumnName" (superfluous anyway), and also make the dynamic expression a bit more explicit:
columns.Add(
new WebGridColumn() {
Header = column.Header,
Format = (item) => #Html.Raw("<text>" + #item.Attributes[column.Name] + "</text>")
}
);
This issue is related to reference variables. You need to have the Format property in terms of the other properties of the WebGridColumn. This is how I would do it:
#{
List<WebGridColumn> columns = new List<WebGridColumn>();
foreach (var column in Model.Columns)
{
var col = new WebGridColumn();
col.Header = column.Name;
col.Format = (item) => #Html.Raw("<text>" + #item.Attributes[col.Header] + "</text>");
columns.Add(col);
}
}