I am using https://vaadin.com/directory/component/file-download-wrapper
with below code
exportButton = new Button("export"));
FileDownloadWrapper buttonWrapper = new FileDownloadWrapper(
new StreamResource(genericGridView.getExportFileCaption(), () -> getExportStream()));
buttonWrapper.wrapComponent(exportButton);
buttonLayout.add(exportButton); //Button Layout is an Horizontal Layout which is added finally in the
main Layout.
and this part of code is written at the loading time of my view. But the method getExportStream method not getting executed(Tried to Put debug in eclipse but it never executed) neither on view load nor in button click event.
Please can you help in this implementation, whether I am doing something wrong here?
You need to add the FileDownloadWrapper to the layout instead of the Button. Otherwise, the FileDownloadWrapper does nothing.
For me the code using FileDownloadWrapper looks correct. So I tend to think that the problem is more related to how you generate the data. I copy here one code snippet from my test apps that works. The CSV export here uses StatefulBeanToCsv and StatefulBeanToCsvBuilder from com.opencsv.opencsv library.
private void export(Grid<Person> grid, TextArea result) {
Set<Person> selection = grid.asMultiSelect().getValue();
Stream<Person> persons = persons = selection.stream();
StringWriter output = new StringWriter();
StatefulBeanToCsv<Person> writer = new StatefulBeanToCsvBuilder<Person>(
output).build();
try {
writer.write(persons);
} catch (CsvDataTypeMismatchException
| CsvRequiredFieldEmptyException e) {
output.write("An error occured during writing: " + e.getMessage());
}
result.setValue(output.toString());
StreamResource resource = new StreamResource("export.csv",
() -> new ByteArrayInputStream(output.toString().getBytes()));
FileDownloadWrapper download = new FileDownloadWrapper(resource);
Button button = new Button("Click to download");
download.wrapComponent(button);
add(download);
}
Related
I'm currently working on a JavaFX project.I'm using Autcomplete TextField of ControlFx .Each time i add new rows in database table, it should to update Autocomplete ,i did this but my problem is showing double Context-Menu ,we can say double autocompletes because i call method that create autocomplete each adding of new elements in table.
When i click a tab editBill i call this method :
public void showEditBill() {
if (!BillPane.getTabs().contains(EditBillTab)) {
BillPane.getTabs().add(EditBillTab);
}
SingleSelectionModel<Tab> selectionModel = BillPane.getSelectionModel();
selectionModel.select(EditBillTab);
/*it should remove the old autocomplete from textfield*/
pushBills(); //Call for cheking new items
}
pushBills method () :
public void pushBills() {
ArrayList list = new ArrayList<>();
bills = new BillHeaderDao().FindAll();
for (int i = 0; i < bills.size(); i++) {
list.add(bills.get(i).getIdClient());
}
//How can i remove the old bind before bind again
autoCompletionBinding = TextFields.bindAutoCompletion(SearchBill, SuggestionProvider.create(list));
}
How i can remove the old autocomplete and bind new automplete?
Just in any case if you need to keep instance of AutoCompletionTextFieldBinding object, thus avoiding use of:
autoCompleteBinding = TextFields.bindingAutoCompletion(TextField,List);
, which will change the instance, we could go a little bit deeper and use this:
// let's suppose initially we have this possible values:
Set<String> autoCompletions = new HashSet<>(Arrays.asList("A", "B", "C"));
SuggestionProvider<String> provider = SuggestionProvider.create(autoCompletions);
new AutoCompletionTextFieldBinding<>(textField, provider);
// and after some times, possible autoCompletions values has changed and now we have:
Set<String> filteredAutoCompletions = new HashSet<>(Arrays.asList("A", "B"));
provider.clearSuggestions();
provider.addPossibleSuggestions(filteredAutoCompletions);
So, through SuggestionProvider, we have "updated" auto completion values.
To avoid doubling of suggestions menu, don't use again (for the 2nd time):
TextFields.bindAutoCompletion(..)
In order to provide updates to the auto-complete suggestion list, retain a reference to the SuggestionProvider and update the suggestion provider instead:
TextField textField = new TextField();
SuggestionProvider suggestionProvider = SuggestionProvider.create(new ArrayList());
new AutoCompletionTextFieldBinding<>(textField, suggestionProvider);
When you want to update the suggestion list:
List<String> newSuggestions = new ArrayList();
//(add entries to list)
suggestionProvider.clearSuggestions();
suggestionProvider.addPossibleSuggestions(newSuggestions);
This will do the trick:
Instead of: TextFields.bindAutoCompletion(textField, list);
, try this:
List<String> strings = new ArrayList<>();
Then create binding between your textField with the list through:
new AutoCompletionTextFieldBinding<>(textField, SuggestionProvider.create(strings));
So any changes, including removing, from the list, will be reflected in the autoCompletion of the textField;
And you will have dynamic filtering of suggestions, showed in pop-up, when user enter some text in textField;
I had the same problem some time ago I try to do as #MaxKing mentions, but it didnt work. I managed to give it a soluciĆ³n even though I don't think it's the right way.
// Dispose the old binding and recreate a new binding
autoCompleteBinding.dispose();
autoCompleteBinding = TextFields.bindingAutoCompletion(TextField,List);
try this:
public void pushBills() {
ArrayList list = new ArrayList<>();
bills = new BillHeaderDao().FindAll();
for (int i = 0; i < bills.size(); i++) {
list.add(bills.get(i).getIdClient());
}
autoCompletionBinding.dispose();
autoCompletionBinding = TextFields.bindAutoCompletion(SearchBill, SuggestionProvider.create(list));
}
I am using a DevExpress MVC Pivot Grid and trying to work out some problems with the loading and saving of layouts. So far I have the following:
I have set my CustomActionRouteValues in the PivotGridSettings as follows:
CustomActionRouteValues = new { Controller = "Home", Action = "PivotGridCustomCallback" },
Which points to the following:
public ActionResult PivotGridCustomCallback(string action, string reportName)
{
if (string.IsNullOrEmpty(reportName))
{
reportName = "Report 1";
}
var settings = PivotGridLayoutHelper.DefaultPivotGridSettings;
if (action == "Save")
{
// TODO: Find a better solution than this. At the moment, if Save is called once, it is then called again every time the user changes the layout.. which is why we have the 'saved' variable here.
bool saved = false;
settings.AfterPerformCallback = (sender, e) =>
{
if (saved)
{
return;
}
SaveLayout(((MVCxPivotGrid)sender).SaveLayoutToString(), reportName);
saved = true;
};
}
else if (action == "Load")
{
// TODO: Find a better solution than this. At the moment, if Load is called once, it is then called again every time the user changes the layout.. which is why we have the 'loaded' variable here.
bool loaded = false;
string layoutString = LoadLayout(reportName);
if (!string.IsNullOrEmpty(layoutString))
{
settings.BeforeGetCallbackResult = (sender, e) =>
{
if (loaded)
{
return;
}
((MVCxPivotGrid)sender).LoadLayoutFromString(layoutString, PivotGridWebOptionsLayout.DefaultLayout);
loaded = true;
};
}
}
ViewBag.PivotSettings = settings;
return PartialView("PivotPartial");
}
The problem, as you can see in the code comments, is that after performing an action just one time, it then gets called EVERY time I make any sort of change. So, for example... say I load a report.. that's fine.. but then when I try expand something or add a field.. or do ANYTHING, nothing seems to happen on the UI.. and I figured out that's because immediately, this code gets called again:
settings.BeforeGetCallbackResult = (sender, e) =>
{
((MVCxPivotGrid)sender).LoadLayoutFromString(layoutString, PivotGridWebOptionsLayout.DefaultLayout);
};
That just keeps resetting the values to the saved layout, which means the UI looks like it's unresponsive when trying to change anything.
This is why I now have the boolean variable called loaded to check if it's already loaded. That works.. but it's an ugly hack.. because it's making unnecessary trips to the server each and every time the user does anything on the pivot grid.
Surely there must be a way to prevent these actions from firing all the time?
From the detailpage's view I try to push a new page on and I get this error: **
System.InvalidOperationException: Page must not already have a parent.
I keep trying different things but nothing works. Is there a way to push a page onto it, I mean, the detailpage is a navigationpage but it is a detailpage. Any and all help is much appreciated.
I am using xamarin forms labs ViewFactory.
//app.cs GetMainPage
var rootPage = ViewFactory.CreatePage<HomeVM>();
//in HomeView.xaml.cs, setting the detailpage to the list of messages
Detail = new NavigationPage(ViewFactory.CreatePage<MessagesVM>());
//This is in the MessagesView to show an individual message with a back button to the list of messages
Navigation.PushAsync(ViewFactory.CreatePage<MessageDetailVM>());
If you already have a NavigationPage, do not create another one to wrap your Detail instance in.
Detail = iewFactory.CreatePage<MessagesVM>();
Navigation.PushAsync(ViewFactory.CreatePage<MessageDetailVM>());
On my part, I also having the same error using MessagingCenter, but also solve it by unsubscribing/disposing after page closing/OnDisappearing.
Hope it helps.
public partial class MainPage : MasterDetailPage
{
public MainPage()
{
InitializeComponent();
MasterBehavior = MasterBehavior.Popover;
MessagingCenter.Subscribe<NavigationPage>(this, "Navigate", (pageItem) =>
{
Detail = pageItem;
IsPresented = false;
});
MessagingCenter.Subscribe<string>(this, "Logout", (s) =>
{
Application.Current.MainPage = new LoginPage("", "");
});
}
protected override void OnDisappearing()
{
MessagingCenter.Unsubscribe<NavigationPage>(this, "Navigate");
MessagingCenter.Unsubscribe<string>(this, "Logout");
base.OnDisappearing();
}
}
Unfortunately, I encountered this error again, and I solve it by using this setting the NavigationPage Parent property to null.
MessagingCenter.Subscribe<NavigationPage>(this, "Navigate", (pageItem) =>
{
pageItem.Parent = null; //solution
Detail = pageItem;
IsPresented = false;
});
Both answers before mine are pointing to the right direction, so this is just an addition. The key is in fact to not create the NavigationPage/NavigationView again.
In my project, I am using static objects for the MasterDetailPage, the NavigationView and the corresponding ViewModels in Xamarin Forms App class;
I am only creating an instance if their Value is null, which is likely to happen only if the app was closed before (no matter if closed by the user or the OS). If the app is still running (resumed), I am just using the already existing objects to restore the state.
This solved all these problems for me, and I hope it is helpful for someone else.
Try using the Navigation property of the Detail object like this:
Detail.Navigation.PushAsync(page);
To push a new page on my Detail I use the code below:
Note there I'm using a ListView with page options in MasterDetailPage
private void ListView_ItemSelected(object sender, SelectedItemChangedEventArgs e)
{
var item = e.SelectedItem as MainMenuItem;
if (item == null)
return;
var page = (Page)Activator.CreateInstance(item.TargetType);
//Detail = new NavigationPage(page);
Detail.Navigation.PushAsync(page);
IsPresented = false;
MasterPage.ListView.SelectedItem = null;
}
I want to call method which will do something in background, but I don't want to change the current view. This is the method:
public ActionResult BayesTraining(string s,string path)
{
XmlParse xp = new XmlParse();
using (StreamWriter sw = System.IO.File.AppendText(path))
{
sw.WriteLine("d:/xml/"+xp.stripS(s)+".xml");
sw.Close();
}
return RedirectToAction("Index");
}
As you can see, I'm currently using RedirectToAction, that just reloads the page after the method is done working. Having in mind that method doesn't effect UI, I don't want to refresh web page every time I've used it. It's job should be done in background. So, how could I call it, without the need to redirect the view?
If you want something you can fire and forget use an ajax call. For instance if you change your action method to
public JsonResult BayesTraining(string s,string path)
{
XmlParse xp = new XmlParse();
using (StreamWriter sw = System.IO.File.AppendText(path))
{
sw.WriteLine("d:/xml/"+xp.stripS(s)+".xml");
sw.Close();
}
return Json("Success");
}
Then in your view bind to the UI event you need to via jQuery, for instance to bind to a button with id of BayesTraining do the following
$("#BayesTraining").click(function(){
$.post('#Url.Action( "BayesTraining" , "ControllerNameHere" , new { s = "stringcontent", path="//thepath//tothe//xmlfile//here//} )', function(data) {
//swallow success here.
});
}
DISCLAIMER: above code is not tested.
Hopefully it'll point you in the right direction.
If the method doesn't affect the UI, does it need to return an ActionResult? Couldn't it return void instead?
public void BayesTraining(string s,string path)
{
XmlParse xp = new XmlParse();
using (StreamWriter sw = System.IO.File.AppendText(path))
{
sw.WriteLine("d:/xml/"+xp.stripS(s)+".xml");
sw.Close();
}
}
I've read several related posts and even posted and answer here but it seems like I was not able to solve the problem.
I have 3 Activities:
Act1 (main)
Act2
Act3
When going back and forth Act1->Act2 and Act2->Act1 I get no issues
When going Act2->Act3 I get no issues
When going Act3->Act2 I get occasional crashes with the following error: java.lang.IllegalStateException: trying to requery an already closed cursor android.database.sqlite.SQLiteCursor#.... This is a ListView cursor.
What I tried:
1. Adding stopManagingCursor(currentCursor);to the onPause() of Act2 so I stop managing the cursor when leaving Act2 to Act3
protected void onPause()
{
Log.i(getClass().getName() + ".onPause", "Hi!");
super.onPause();
saveState();
//Make sure you get rid of the cursor when leaving to another Activity
//Prevents: ...Unable to resume activity... trying to requery an already closed cursor
Cursor currentCursor = ((SimpleCursorAdapter)getListAdapter()).getCursor();
stopManagingCursor(currentCursor);
}
When returning back from Act3 to Act2 I do the following:
private void populateCompetitorsListView()
{
ListAdapter currentListAdapter = getListAdapter();
Cursor currentCursor = null;
Cursor tournamentStocksCursor = null;
if(currentListAdapter != null)
{
currentCursor = ((SimpleCursorAdapter)currentListAdapter).getCursor();
if(currentCursor != null)
{
//might be redundant, not sure
stopManagingCursor(currentCursor);
// Get all of the stocks from the database and create the item list
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
((SimpleCursorAdapter)currentListAdapter).changeCursor(tournamentStocksCursor);
}
else
{
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
}
}
else
{
tournamentStocksCursor = mDbHelper.retrieveTrounamentStocks(mTournamentRowId);
}
startManagingCursor(tournamentStocksCursor);
//Create an array to specify the fields we want to display in the list (only name)
String[] from = new String[] {StournamentConstants.TblStocks.COLUMN_NAME, StournamentConstants.TblTournamentsStocks.COLUMN_SCORE};
// and an array of the fields we want to bind those fields to (in this case just name)
int[] to = new int[]{R.id.competitor_name, R.id.competitor_score};
// Now create an array adapter and set it to display using our row
SimpleCursorAdapter tournamentStocks = new SimpleCursorAdapter(this, R.layout.competitor_row, tournamentStocksCursor, from, to);
//tournamentStocks.convertToString(tournamentStocksCursor);
setListAdapter(tournamentStocks);
}
So I make sure I invalidate the cursor and use a different one. I found out that when I go Act3->Act2 the system will sometimes use the same cursor for the List View and sometimes it will have a different one.
This is hard to debug and I was never able to catch a crashing system while debugging. I suspect this has to do with the time it takes to debug (long) and the time it takes to run the app (much shorter, no pause due to breakpoints).
In Act2 I use the following Intent and expect no result:
protected void onListItemClick(ListView l, View v, int position, long id)
{
super.onListItemClick(l, v, position, id);
Intent intent = new Intent(this, ActivityCompetitorDetails.class);
intent.putExtra(StournamentConstants.App.competitorId, id);
intent.putExtra(StournamentConstants.App.tournamentId, mTournamentRowId);
startActivity(intent);
}
Moving Act1->Act2 Act2->Act1 never gives me trouble. There I use startActivityForResult(intent, ACTIVITY_EDIT); and I am not sure - could this be the source of my trouble?
I would be grateful if anyone could shed some light on this subject. I am interested in learning some more about this subject.
Thanks,D.
I call this a 2 dimensional problem: two things were responsible for this crash:
1. I used startManagingCursor(mItemCursor); where I shouldn't have.
2. I forgot to initCursorAdapter() (for autocomplete) on onResume()
//#SuppressWarnings("deprecation")
private void initCursorAdapter()
{
mItemCursor = mDbHelper.getCompetitorsCursor("");
startManagingCursor(mItemCursor); //<= this is bad!
mCursorAdapter = new CompetitorAdapter(getApplicationContext(), mItemCursor);
initItemFilter();
}
Now it seems to work fine. I hope so...
Put this it may work for you:
#Override
protected void onRestart() {
// TODO Auto-generated method stub
super.onRestart();
orderCursor.requery();
}
This also works
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
startManagingCursor(Cursor);
}