I would like to show a series of financial transactions in a TableView.
Each Transaction consists of a Date, a Description and an Amount.
I can make this work using bindings if I treat all the cells as Text using the example shown in a reply to another question. This allows in cell editing which is my goal.
But I can't get it to work on the date and amount columns, I think I need a separate cell factory for each cell type and a possibly a separate updateItem method but I'm stuck.
Any pointers to an example or suggestions would be helpful.
You may want to check out the DataFX project at:
http://www.javafxdata.org/
and specifically the cell factories like:
http://www.javafxdata.org/javadoc/org/javafxdata/control/cell/TextFieldCellFactory.html
DataFX contains custom cell factories for several data types, tables, lists and tree views. Assuming that for example your amount has a double type, you could write something similar like that in a subclass of TableColum
(replace ??? by the class name of the class that represents a row in your table):
setCellFactory(TextFieldCellFactory.<???, Number>forTableColumn(new Callback<String,Number>(){
#Override
public Number call(String newValueStr) {
double newValue = Double.parseDouble(newValueStr);
return newValue;
}));
setOnEditCommit(new EventHandler<CellEditEvent<???, Number>>() {
#Override
public void handle(CellEditEvent<???, Number> t) {
double newValue = t.getNewValue().doubleValue();
// do something with the double value the user entered here
}
});
}
}
I hope that at least gives you some direction. I have left out Exception handling for clarity.
Related
#When i use SXSSF to write a file,it happend,but i don`t know why.Here is my code:#
SXSSFWorkbook workbook = new SXSSFWorkbook()
SXSSFSheet currentSheet = workbook.createSheet()
SXSSFRow row = sheet.createRow(0);
SXSSFCell cell = row.createCell(0);
cell.setCellValue( obj);
##Now,the log will show "SXSSF doesn't support Rich Text Strings, any formatting information will be lost".##
This log will keep printing, I don't know the exact fix for it but I found work around solution to avoid unnecessary logging.
Step 1: Create your own rich text method
protected XSSFRichTextString richTextString(Object object) {
return new XSSFRichTextString((String) object);
}
Step 2: While assigning value to cell call the above method pass whatever object to it.
protected void addCell(Workbook workbook, Row row, Integer i, Object
object) {
Cell cell = row.createCell(i);
cell.setCellValue(richTextString(object));
}
This might be more of a Java question, but how would you access values (say from a textfield) of a given view/class from a different class? For example if there was a TextField t1 that is in the MainView, and I wanted to get its current value for a computation in a different class. And is there a more Vaadin-specific approach here?
That can depend on the use case specifically. Since you mentioned a TextField value I assume the value is not yet stored in the DB, it's just on the UI yet -> I rule out singleton spring services.
A few ideas:
If the MainView and the different class are nested components and it's viable and not really complicated across a lot of classes... then probably passing it down the way when creating the sub-component. This is a naive solution - it can get pretty messy.
MainView() {
var t1 = new TextField();
var d = new Different(t1);
}
Fire and listen to Vaadin Component events. If you want really loose coupling, the most universal would be to use the UI instance as the event bus.
// listen in different class
ComponentUtil.addListener(attachEvent.getUI(), CloseMenuEvent.class, e -> closeMenu());
// fire change in MainView
ComponentUtil.fireEvent(ui, new CloseMenuEvent(ui))
A more specific version of number 2. is to pass the ValueChangeListener of the MainView's t1 to the different class.
MainView() {
var t1 = new TextField();
var d = new DifferentClass();
t1.addValueChangeListener(d::t1Changed)
add(t1, d);
}
Extract the common field to a third party, to a third class. Use a #UIScoped spring bean (#SpringComponent, #Service, ...) that will hold that field, and inject it to both MainView and the different class.
#Route
public class MainView extends VerticalLayout {
public MainView(Model m, Different d) {
add(m.t1, d);
}
}
#Scope(SCOPE_PROTOTYPE)
public class Different extends Component {
public Different(Model m) {
// something with m.t1
}
}
#UIScoped
public class Model {
public final TextField t1 = new TextField(); // TODO use getter
}
You could change the 4th approach by keeping String in Model and having a value change listener that updates it.
I have an array of view model. Now I want to check that view model array to contain a word within an array.
public IQueryable<CategorisedPostViewModel> GetRelatedPostbyCategories(string categories)
{
var ctries = categories.Split(',');
var result = GetAllCategoriedPost().**Where(p=>p.CategoryName.Contains(ctries)).**OrderByDescending(c => c.Published);
return result;
}
How can I search that bold portions without loop?
We may assume for simplicity,
p.categoryName="jerry,tom,ema"
and
ctries={"Gates","jerry","Jobs","ema"}
I want to check if any ctries is found on p.categoryName. Please help me. Thanks in advance.
To check if any category name is present in ctries try, Intersect
p.categoryName.Intersect(tries).Any()
I have an array of arrays, theMealIngredients = [[]]
I'm creating a newMeal from a current meal and I'm basically copying all checkmarked ingredients into it from the right section and row from a tableview. However, when I use the append, it obviously doesn't know which section to go in as the array is multidimensional. It keeps telling me to cast it as an NSArray but that isn't what I want to do, I don't think.
The current line I'm using is:
newMeal.theMealIngredients.append((selectedMeal!.theMealIngredients[indexPath.section][indexPath.row])
You should re-model your data to match its meaning, then extract your tableview from that. That way you can work much more easily on the data without having to fuss with the special needs of displaying the data. From your description, you have a type, Meal that has [Ingredient]:
struct Meal {
let name: String
let ingredients: [Ingredient]
}
(None of this has been tested; but it should be pretty close to correct. This is all in Swift 3; Swift 2.2 is quite similar.)
Ingredient has a name and a kind (meat, carbs, etc):
struct Ingredient {
enum Kind: String {
case meat
case carbs
var name: String { return self.rawValue }
}
let kind: Kind
let name: String
}
Now we can think about things in terms of Meals and Ingredients rather than sections and rows. But of course we need sections and rows for table views. No problem. Add them.
extension Meal {
// For your headers (these are sorted by name so they have a consistent order)
var ingredientSectionKinds: [Ingredient.Kind] {
return ingredients.map { $0.kind }.sorted(by: {$0.name < $1.name})
}
// For your rows
var ingredientSections: [[Ingredient]] {
return ingredientSectionKinds.map { sectionKind in
ingredients.filter { $0.kind == sectionKind }
}
}
}
Now we can easily grab an ingredient for any given index path, and we can implement your copying requirement based on index paths:
extension Meal {
init(copyingIngredientsFrom meal: Meal, atIndexPaths indexPaths: [IndexPath]) {
let sections = meal.ingredientSections
self.init(name: meal.name, ingredients: indexPaths.map { sections[$0.section][$0.row] })
}
}
Now we can do everything in one line of calling code in the table view controller:
let newMeal = Meal(copyingIngredientsFrom: selectedMeal,
atIndexPaths: indexPathsForSelectedRows)
We don't have to worry about which section to put each ingredient into for the copy. We just throw all the ingredients into the Meal and let them be sorted out later.
Some of this is code is very inefficient (it recomputes some things many times). That would be a problem if ingredient lists could be long (but they probably aren't), and can be optimized if needed by caching the results or redesigning the internal implementation details of Meal. But starting with a clear data model keeps the code simple and straightforward rather than getting lost in nested arrays in the calling code.
Multi-dimentional arrays are very challenging to use well in Swift because they're not really multi-dimentional. They're just arrays of arrays. That means every row can have a different number of columns, which is a common source of crashing bugs when people run off the ends of a given row.
After upgrading to MT 4.0, my TableViews that previously were displaying indexes on the right hand border are no longer working. The tableview still displays in sections and works properly, but the index is not displaying.
I have these three methods defined in my UITableViewSource, and all three appear to be working:
public override string[] SectionIndexTitles(UITableView tableView)
public override int SectionFor(UITableView tableView, string Title, int atIndex)
public override string TitleForHeader(UITableView tableView, int section)
Is anyone else having this problem? Is this a bug with MT 4.0?
This is a known bug.
It appears that UITableView is not retaining the returned array, you can use
the following to work around this issue while we investigate it further:
NSArray array;
[Export ("sectionIndexTitlesForTableView:")]
public NSArray SectionTitles (UITableView tableview)
{
if (array == null) {
string[] titles = new string[RowsInSection(tableview, 0)];
for (int index = 0; index < titles.Length; index++)
titles[index] = index.ToString();
array = NSArray.FromStrings (titles);
}
return array;
}
This was showing to me just numbers (index for each item of the section 0 (like A letter of the index), so I found that must change this to:
NSArray array;
[Export ("sectionIndexTitlesForTableView:")]
public NSArray SectionTitles (UITableView tableview)
{
if (array == null)
{
array = NSArray.FromStrings (SectionIndexTitles(tableview));
}
return array;
}
To all people who don't get the workaround to work correctly:
For me it was because I left the MonoTouch override method SectionIndexTitles in there - as soon as I removed it (or in my case renamed it so it can be called from the workaround), it worked as described :)
Getting the same problem, but the above fix did not work, I am sure it is probably something simple that I am doing wrong. The below methods are part of a UITableViewSource. All working as it was before MT 4.0, however the textual Index is not appearing. Debug output listed below the code shows that SectionTitles is not being called. Any thoughts on how this differs from the solution above, and how to get it working? Happy to start a new thread on this, but thought that it might be useful to have more information on this question instead.
NSArray array;
[Export ("sectionIndexTitlesForTableView:")]
public NSArray SectionTitles(UITableView tableview)
{
Debug.WriteLine("SectionTitles");
if (array == null)
{
array = NSArray.FromStrings(SectionIndexTitles(tableview));
}
return array;
}
public override string[] SectionIndexTitles(UITableView tableView)
{
Debug.WriteLine("SectionIndexTitles");
var sectionIndexTitles = Root.Sections.Select(section => section.IndexTitle ?? string.Empty);
var applySectionIndexTitles = sectionIndexTitles.Any (sectionIndexTitle => !string.IsNullOrEmpty (sectionIndexTitle));
foreach (string s in sectionIndexTitles)
{
Debug.WriteLine(s);
}
Debug.WriteLine("applySectionIndexTitles = " + applySectionIndexTitles);
return applySectionIndexTitles ? sectionIndexTitles.ToArray () : null;
}
Debug output:
SectionIndexTitles
A
B
C
D
E
F
G
H
J
K
L
M
N
O
P
R
S
T
W
applySectionIndexTitles = True
Wow, the answers here are a extremely misleading. Where do I start?
First, why are the examples using a backing NSArray? Why not a string [] for the backing data? Just because the method returns a NSArray doesn't mean you have to back it with an NSArray. Yikes. Why would you use an NSArray unless you have to. You don't have to here.
Second, realistically, I always store my index titles in a backing string []. That is normal use I'd say. Why wouldn't you do that anyway? The answers here make it sounds like it's a special case or something where you have to store it. As far as I know you are always responsible for doing that anyway. And another example relying on the cells to get data... Why on earth? If you can't simply use an array then get a clue that your array is out of scope or something.
Also, some people mentioned to not override as you normally would. Ummm... I don't know about that. That completely contradicts all the monotouch code I've seen. I've seen a lot of examples do both and it makes sense. Look at some of the template UIViewController constructors. The internal calls that explicitly reference selectors will need the selector. Normally you wouldn't need one but in this case apparently something internal is broken referencing the selector. That is NOT a reason to ditch overriding it as you normally would. You still need to override it in case you have some external call that came from your own managed code. You should absolutely still override it. Unless you always explicitly referencing selectors in YOUR code... then keep it overriden.
Anyway, a lot of this is my general monotouch understanding and I could be wrong. I mean, I don't know... I'm seriously not trying to criticize. I just had to comment because it looks like to me there is A LOT of bad information in this thread and I'm hoping this post will help someone who might be getting misinformed.