I'm trying to use the same page for 3 tabs in TabbedPage. But each tab has to display different data in the listview. Is there a way to set a parameter for each tab?
Example
<local:Sales Title="Pending"
Icon="ic_shortcut_home.png"
ClassId="pending"/>
<local:Sales Title="Posted"
Icon="ic_shortcut_home.png"
ClassId="posted"/>
<local:Sales Title="Uploaded"
Icon="ic_shortcut_home.png"
ClassId="uploaded"/>
I tried using ClassId, and Title to get their difference but I'm having trouble retrieving the ClassId in the Sales class constructor, are there any other ways to get the output I want?
public Sales()
{
InitializeComponent();
BindingContext = this;
salesCollection = new ObservableCollection<Head>();
initLvw();
Console.WriteLine(Title); //returns null
Console.WriteLine(ClassId); // returns null
}
You can load data in OnAppearing method:
protected override void OnAppearing()
{
base.OnAppearing();
Console.WriteLine(ClassId + "OnAppearing");
BindingContext = this;
salesCollection = new ObservableCollection<Head>();
initLvw();
}
Or load data with a little delay in constructor:
public AboutPage()
{
InitializeComponent();
Task.Run(async () =>
{
await Task.Delay(200);
Console.WriteLine(ClassId + "AboutPage");
BindingContext = this;
salesCollection = new ObservableCollection<Head>();
initLvw();
});
}
Related
i need to redirect to another page in ViewModel after performing some action. I have button and set my command, however if i load the page fort the first time then i get an error "Please use navigation page" application fails and i start it again and try to load the page and it works, but if i delete the app from emulator and try all over again i have the same process.
public ICommand FilterItemsCommand { get; private set; }
public FilterArticlesForPurchaseViewModel()
: base()
{
Task.Run(async () => await LoadAllDataForArticlesAndCategories()).Wait();
FilterItemsCommand = new Command(async () => await FilterItems());
}
private async Task FilterItems()
{
await Application.Current.MainPage.Navigation.PushAsync(new ArticlesForPurchaseFiltered());
}
App
MainPage = new NavigationPage(GetMainPage());
I have also tried this
Application.Current.MainPage = new NavigationPage(new ArticlesForPurchaseFiltered());
But then i cant go back to previous page and if i use android back button the application fails
BTW i am using master detail
You can add INavigation navigation to your ViewModel's constructor like following code.
public ItemsViewModel(INavigation navigation)
{
Title = "Browse";
Items = new ObservableCollection<Item>();
LoadItemsCommand = new Command(async () => await ExecuteLoadItemsCommand());
FilterItemsCommand = new Command(() => { navigation.PushModalAsync(new Page1()); });
MessagingCenter.Subscribe<NewItemPage, Item>(this, "AddItem", async (obj, item) =>
{
var newItem = item as Item;
Items.Add(newItem);
await DataStore.AddItemAsync(newItem);
});
}
When you binding the viewmodel, you can add the attribute like following code.
public ItemsPage()
{
InitializeComponent();
BindingContext = viewModel = new ItemsViewModel(Navigation);
}
If you want to achieve the navigation in the viewModel, you can use
// this way you need add `MainPage =new NavigationPage( new MainPage());` in app.xaml.cs
navigation.PushAsync(new Page1());
// this way you do not need `MainPage =new NavigationPage( new MainPage());` in //app.xaml.cs, just used it directly
navigation.PushModalAsync(new Page1());
I try to use my custom class which I have created in my script (the script is written in Nashorn) and after that I try to use this custom class to fill in as items in combobox. I know that if I want to see correct values in combobox that the class has to override method toString, but in this case I do not know much how can be overriden this method in my custom class written in Nahorn.
Below I provide my code where the variables cmbCategories is JavaFX combobox and CategoryItem which I try to use as object to fill in the items in combobox and display as category name.
I would appreciate any suggestion or ideas how can be this problem resolved.
var ClientBuilder = Java.type("javax.ws.rs.client.ClientBuilder")
var Platform = Java.type("javafx.application.Platform")
var Executors = Java.type("java.util.concurrent.Executors")
var Response = Java.type("javax.ws.rs.core.Response")
var String = Java.type("java.lang.String")
var List = Java.type("java.util.ArrayList")
Executors.newSingleThreadExecutor().execute(function () {
print("Calling for category data...")
var categoryData = ClientBuilder
.newClient()
.target(String.format("%s%s", "http://localhost:8080", "/client/action/categories"))
.request()
.get()
if(categoryData.getStatus() == Response.Status.OK.getStatusCode()) {
var categories = JSON.parse(categoryData.readEntity(String.class))
var categoryItems = new List();
for each (var category in categories) {
categoryItems.add(new CategoryItem(category.id, category.category))
}
Platform.runLater(function() {
cmbCategory.getItems().addAll(categoryItems);
});
} else {
print(categoryData.getEntity().toString());
}
})
function CategoryItem(id, name) {
this.id = id;
this.name = name;
this.toString = function () {
return this.name;
}
}
Use the ScriptEngine to retrieve an appropriate string in the cellValueFactory of the ComboBox.
Simplified example
#Override
public void start(Stage primaryStage) throws Exception {
ScriptEngineManager manager = new ScriptEngineManager();
final ScriptEngine engine = manager.getEngineByMimeType("application/javascript");
ComboBox<Object> comboBox = new ComboBox();
comboBox.setCellFactory(c -> new ListCell<Object>() {
#Override
protected void updateItem(Object item, boolean empty) {
super.updateItem(item, empty);
if (empty || item == null) {
setText("");
} else {
Bindings bindings = new SimpleBindings();
bindings.put("a", item);
try {
// use script engine to retrieve text
setText(Objects.toString(engine.eval("a.name", bindings)));
} catch (ScriptException ex) {
setText("Error");
}
}
}
});
comboBox.setButtonCell(comboBox.getCellFactory().call(null));
Bindings b = new SimpleBindings();
b.put("cmbCategory", comboBox);
engine.eval("function CategoryItem(id, name) {this.id = id;this.name = name;}\n"
+"var Platform = Java.type(\"javafx.application.Platform\")\n"
+ "var categories = [new CategoryItem(1, 'a'), new CategoryItem(2, 'b'), new CategoryItem(3,'c')]\n"
+ "for each (var category in categories) {cmbCategory.getItems().add(category);}", b);
Scene scene = new Scene(new StackPane(comboBox));
primaryStage.setScene(scene);
primaryStage.show();
}
I don't see the purpose of using JavaScript for this though. Everything you do in the javascript code could be done from java code more efficiently...
I'm trying to figure out how to add text to the bottom of a list box and display it. In WPF with code behind, I would grab the ScrollViewer and manipulate it, but I can't figure out how to do it with Caliburn...
You have a couple options.
1) In your ViewModel you can call GetView and cast it to your view type and get a reference to the ScrollViewer. Something like:
var myView = this.GetView() as MyView;
var myScrollView = myView.MyScrollView;
That works fine but isn't ideal if you're trying to not couple the view to the view model.
Option 2) is to implement IResult, see docs here.
public class ScrollViewResult : IResult
{
public event EventHandler<ResultCompletionEventArgs> Completed = delegate { };
private ScrollViewResult ()
{
}
public void Execute (ActionExecutionContext context)
{
var view = context.View as FrameworkElement;
var scrollViewer = FindVisualChild<ScrollViewer>(view);
//do stuff to scrollViewer here
Completed (this, new ResultCompletionEventArgs { });
}
private static TChildItem FindVisualChild<TChildItem> (DependencyObject obj)
where TChildItem : DependencyObject
{
for (var i = 0; i < VisualTreeHelper.GetChildrenCount (obj); i++)
{
var child = VisualTreeHelper.GetChild (obj, i);
if (child != null && child is TChildItem)
return (TChildItem)child;
var childOfChild = FindVisualChild<TChildItem> (child);
if (childOfChild != null)
return childOfChild;
}
return null;
}
//this isn't required of course but comes in handy for
//having a static method and passing parameters to the
//ctor of the IResult
public static IResult DoSomething ()
{
return new ScrollViewResult ();
}
Then you can call it like:
public IEnumerable<IResult> SomeAction()
{
yield return ScrollViewResult.DoSomething();
}
If I click on a button of my Silverlight app, another third-party web app must gets some data.
My experience, until now, has been to create web service functions that you can call when you need, but in this case I have to give the possibility to the customer to "handle the click event on the button". In the actual case the third-party app is ASP.Net, but, if it were possible, I would like to do something portable.
Before to start with some crazy idea that will comes in my mind, I would ask: How would you do that?
Pileggi
I Use This Class To Create And Post a Form Dynamically
public class PassData
{
public static PassData Default = new PassData();
public void Send(string strUrl, Dictionary<string, object> Parameters, string ContainerClientID = "divContainer")
{
var obj = HtmlPage.Document.GetElementById(ContainerClientID);
if (obj != null)
{
HtmlElement divContainer = obj as HtmlElement;
ClearContent((HtmlElement)divContainer);
HtmlElement form = HtmlPage.Document.CreateElement("form");
form.SetAttribute("id", "frmPostData");
form.SetAttribute("name", "frmPostData");
form.SetAttribute("target", "_blank");
form.SetAttribute("method", "POST");
form.SetAttribute("action", strUrl);
if (Parameters != null)
foreach (KeyValuePair<string, object> item in Parameters)
{
HtmlElement hidElement = HtmlPage.Document.CreateElement("input");
hidElement.SetAttribute("name", item.Key);
hidElement.SetAttribute("value", item.Value.ToString());
form.AppendChild(hidElement);
}
divContainer.AppendChild(form);
form.Invoke("submit");
ClearContent((HtmlElement)divContainer);
}
}
private void ClearContent(System.Windows.Browser.HtmlElement obj)
{
foreach (HtmlElement item in obj.Children)
{
obj.RemoveChild(item);
}
}
}
divContainer is id of a div in html
I am calling few methods on a button click.
functionA()
functionB()
functionC()
All three functions are independent from each other and they take long time to execute. I checked and found that by threading I can run all three together which will save the execution time.
As I am new to threading concept, could anyone please guide me the simplest way I can do threading in scenario or other way which will be useful in this scenario.
EDIT
One more problem in the same function:
I am binding 5 gridviews after the three functions execution. Like this
gv1.DataSource = GetData("Mill");
gv1.DataBind();
gv2.DataSource = GetData("Factory");
gv2.DataBind();
gv3.DataSource = GetData("Garage");
gv3.DataBind();
gv4.DataSource = GetData("Master");
gv4.DataBind();
They all are using the same method for getting the result and they are also taking time to load. Is there any way I can run them parallel too? I afraid, because they are using same method to get the data. Is it possible to do threading for them. How ?
I am not sure how Parallel.Invoke() decides what to execute in parallel, but if you want an assurance that they will execute in parallel, use threads:
var t1 = new Thread(MySlowFunction);
t1.IsBackground = true;
t1.Start();
var t2 = new Thread(MySlowFunction);
t2.IsBackground = true;
t2.Start();
# To resync after completion:
t1.Join();
t2.Join();
Or even better, use the ThreadPool:
ThreadPool.QueueUserWorkItem(MyWork);
Remember to handle your thread exceptions.
The simplest answer is to use MSDN: Parallel.Invoke().
You should also consider: Asynchronous Pages.
Try using System.Threading.Tasks namespace
Something like
var task1 = Task.Factory.StartNew(() => DoA());
var task2 = Task.Factory.StartNew(() => DoB());
var task3 = Task.Factory.StartNew(() => DoC());
Task.WaitAll(task1, task2, task3);
http://www.codethinked.com/net-40-and-systemthreadingtasks
Here's an example which will execute the 4 tasks in parallel:
public partial class _Default : System.Web.UI.Page
{
public class MyViewModel
{
public int Id { get; set; }
public string Name { get; set; }
}
protected void Page_Load(object sender, EventArgs e)
{
}
protected void BtnBindClick(object sender, EventArgs e)
{
// we define the input for the tasks: each element consists
// of the grid we are willing to bind the results at the end and
// some optional parameter we want to pass to the GetData function
var inputs = new[]
{
new { Grid = gv1, Input = "Mill" },
new { Grid = gv2, Input = "Factory" },
new { Grid = gv3, Input = "Garage" },
new { Grid = gv4, Input = "Master" },
};
// define the tasks we want to execute in parallel
var tasks = inputs
.Select(x => Task.Factory.StartNew(
() => new { Grid = x.Grid, Output = GetData(x.Input) })
)
.ToArray();
// define a task which will be executed once all tasks have finished
var finalTask = Task.Factory.ContinueWhenAll(tasks, x => x);
// wait for the final task
finalTask.Wait();
// consume the results
foreach (var item in finalTask.Result)
{
if (item.Exception == null)
{
// if no exception was thrown for this task we could bind the results
item.Result.Grid.DataSource = item.Result.Output;
item.Result.Grid.DataBind();
}
}
}
private MyViewModel[] GetData(string input)
{
// Simulate slowness
Thread.Sleep(1000);
return Enumerable.Range(1, 5).Select(x => new MyViewModel
{
Id = x,
Name = input
}).ToArray();
}
}