ListView add filter on another ListView item selection changed - xaf

I'm currently studying XAF (expressApp Framework) for my work and theres not much good tutorials on the web about it so I went here to ask.
I have a Customers table and a Product table with many-many relationship.
I created a dashboard view where I displayed listviews for both Customers and Products. What I want to know is how can I changed the values on Product listview or add filter to it whenever I select a customer?
I managed to acces the SelectionChanged event of the Customers listview by creating a view controller.
protected override void OnActivated()
{
base.OnActivated();
View.SelectionChanged += ViewOnSelectionChanged;
}
private void ViewOnSelectionChanged(object sender, EventArgs eventArgs)
{
var id = ((Customers) View.CurrentObject).Oid;
}
The event works everytime I select an item in the listview.
I was planning to filter the Products listview using the Customers' Oid.
How will I able to do that?
And also if you can give me some links for a good XAF tutorial, I would appreciate it.
Thank you.

To apply a filter to a ListView you need to add criteria to collectionsource. See the link:
https://documentation.devexpress.com/#eXpressAppFramework/CustomDocument112722

Related

Grid filled by a data provider: how to trigger an action after refreshment?

In Vaadin 8.2, I have a Grid bound to a bean using a data provider (AbstractBackEndDataProvider). Data is fetched from a DB, filters are applied:
Grid grid = new Grid<>();
grid.setDataProvider(dataProvider.withConfigurableFilter()); // dataProvider derives from AbstractBackEndDataProvider<T,F>
The essential flow is the following: user inputs an item id in a form and submits, a submit event listener gets the user input, creates a new filter and updates the data provider:
filterSubmitButton.addClickListener(event -> {
try {
ItemListFilter filter = new ItemListFilter(
itemFilter.getValue(), // itemFilter = new TextField();
);
filterBinder.writeBean(filter);
dataProvider.setFilter(filter);
} catch (ValidationException e) {
//...
}
});
When the data provider gets the filter updated it calls a service to fetch new items from DB with the filter applied (to the DB query). Vaadin takes care of refreshing the Grid with new data afterwards.
What I want is to have a callback at this last moment. Say an use case would be to check if a filtered fetched result set contains only one item, to select this item in the Grid (which in its turn will trigger an event showing item details in another pane). Or to select the first grid row after initial list is loaded
But the problem is that there is neither grid.addRefreshListener() nor dataProvider.addRefreshmentListener(). Any other listeners do not seem to apply in this case.
Thanks for any help in advance.
The only solution I've found is a trade-off.
The item list presenter (which handles the view with the grid) passes its com.vaadin.event.EventRouter to dataProvider (I've modified the dataProvider to hold an EventRounter as a member). And now instead of streaming DB results directly from the dataProvider I fire an event that the data is fetched (using EventRouter). The presenter can subscribe to this event and then delegate it to the presenter of the details panel. There you can read the fetched results (the event contains them), check if there's only one entry and open it by id.
public class ListItemDataProvider extends AbstractBackEndDataProvider<Item, ItemFilter> {
//...
#Override
protected Stream<Item> fetchFromBackEnd(Query<Item, ItemFilter> query) {
// ...
List<Item> fetchedResults = service.fetch(query.getOffset(), query.getLimit(), orderBy, getFilter(query));
eventRouter.fireEvent(new FilteredDataFetchedEvent(this, fetchedResults));
return fetchedResults.stream();
}
}
#Controller
#Scope(ConfigurableBeanFactory.SCOPE_PROTOTYPE)
public class ItemListPresenter {
// ...
public void addFilteredDataFetchedListener(ItemListView.FilteredDataFetchedListener listener) {
eventRouter.addListener(FilteredDataFetchedEvent.class, listener, FilteredDataFetchedListener.FILTERED_DATA_FETCHED);
}
}
Few notes:
This is not exactly what I needed. Yes, I can do the most of my use case, if the filter is applied the list is reloaded and the details view gets the event to reload too. But I can't re-use the "selectionChanged" event listeners for this and actually can't select a row in the grid at all (just because the event from dataProdiver is thrown before the grid is updated).
This is sort of a dirty trick, because now the dataProvider throws events and deals with eventRouters of views/presenters. On the other hand Vaadins data providers anyway do allow to subscribe on events. Using that out-of-box grid-dataProvider reactive binding we just don't have an event fired after data is fetched, so we do it in a custom way.
What could also work is use the given Vaadin's subscriber dataProvider.addDataProviderListener and delegate from there an event containing the filled filter and just act independently catching that event in the details panel. But then you would need to execute sql queries twice (which can be costly) or cache them etc. This brings no benefits in comparison to the given and is still a trade-off.
When you invoke dataprovider.refreshAll(), the associated grid is automatially refreshed. Therefore, after following lines in your code:
filterBinder.writeBean(filter);
dataProvider.setFilter(filter);
add logic to get size of returned records (eg. dataprovider.size()) and if that equals one (01), invoke some other logic to select the one record and display its details in other panel.

MVC Data Form Entry with DataGrid (CRUD)

I am tasked to change our Silverlight(SL) application to MCV since the development lifecycle of SL has already been stopped. I am new to MVC but I can't find a good tutorial how to do a simple CRUD with MVC. Basically, the requirements are
1.) in the UI, there should be two pane, left and right.
2.) In left pane, a grid/data grid view of list of "Student" entity and on the
3.) right side is a data form which displays the Student's details.
4.) The details in right pane, the data form, will change as you select an item in left pane, the data grid.
5.) The data form should be able to do the CRUD functionality.
I am very desperate to find a tutorial but I can't find one that fits my needs. I will be very thankful to those who can help me with this by giving some links or video tutorial. Hope to read comments that could help.
Instead of writing some error free code, I am going to give some directions how to do this with some pseudo code. This will help you to get started.
1.) in the UI, there should be two pane, left and right.
How about adding 2 divs to your page. Try playing with the CSS (Width 50% ? float : Left etc..). This page will be the razor view of Item 2 described below.
2.) In left pane, a grid/data grid view of list of "Student" entity
You will have to create an action method called List (or whatever you like). Inside that you need to query your db and get the students, convert that to a list of view models and send it to the view. In the view, you loop through the items and display a grid, i mean an HTML table.
public ActionResult List()
{
var list= new List<StudentViewModel>();
//Hard coded for demo. you may replace with values from your db
list.Add(new StudentViewModel { Id=1, Name="Shyju" });
return View(list);
}
The view model is a simple POCO
public class StudentViewModel
{
public int Id {set;get;}
public string Name {set;get;}
}
So your List.cshtml view will be strongly typed to a list of StudentViewModel
#model List<StudentViewModel>
<table>
#foreach(var item in Model)
{
<tr>
<td>#item.Name</td>
</tr>
}
</table>
3.) right side is a data form which displays the Student's details.
Add HTML markup for creating a form ,Input fields and a save button.
will change as you select an item in left pane, the data grid.
Add some jQuery code to listen to the click event on the table row, read the StudentId (you can set this as the data attribute value of the tr) and use that Id and make an ajax call to get the data about that student, load that in the input fields.
Update the table markup to have the data attribute
<tr class="myTr" data-studid="#item.Id"><td>#item.Name</td></tr>
The javascript to listen to the click event on the tr
$(function(){
$("tr.myTr").click(function(e){
e.preventDefault();
var studId=$(this).data("stupid");
var url ="#Url.Action("Details","Student")";
//make an ajax call to get the student details
$.getJSON(url+"?id="+studId,function(res){
$("#NameFieldId").val(res.Name);
});
});
});
You need to have a Details action method to give a student detail in json format
public ActionResult Details(int id)
{
var student = new StudentViewModel();
student.Name="Read from DB and set this";
return Json(student,JsonReqestBehaviour.AllowGET);
}
5.) The data form should be able to do the CRUD functionality.
using jQuery ajax, post the form to an http post action method and save it there. Check this and this and this for reference.

searchable grid using knockout in mvc

I need solution for my problem on urgent basis, I am new with mvc, knockout please provide me sample code for my problem. any help will be highly appreciated.
suppose I have an observable array in my viewmodel i.e
var viewmodel = {
vendorproviders : ko.observablearray([])
}
where vendorproviders list consist of multiple attributes like id, name, country, address etc
I want to populate that array in my grid where each row will have a select button, when that button is clicked it should post the id to my controller action either by submitting or by ajax call.
Furthor more that grid should be searchable like if there is a separate text box, based on the value of text box grid should display matching providers else display all providers.
when user search for particular provider grid should populate from observable array instead of making call at server again and again to pupulate the observable array.
I would suggest starting here.
http://learn.knockoutjs.com/#/?tutorial=intro
What you are talking about is all the basic functionality of the tools you referenced.

Caliburn Micro Update RowDetails of a Datagrid

Let me explain my problem. I am working with Caliburn Micro and have a datagrid where a ObservableCollection is being binded as an Itemsource:
private static ObservableCollection<Models.GamesProperties> _dgGames;
public ObservableCollection<Models.GamesProperties> DgGames
{
get { return _dgGames; }
set
{
_dgGames = value;
NotifyOfPropertyChange(() => DgGames);
}
}
So, when I load my data from my database, the collection will be filled and binded to my datagrid (called DgGames)
Everything is fine so far. I have defined for each DataRow "DataRowDetails". Contains an ImageSource, some TextBlocks and so on. The mentioned collection above contains also those DataRowDetails.
I have now created another View and ViewModel for a dialog window in order to change the DataRowDetails. It does work, but the datagrid (DgGames) won't apply these changes. It does not show any update i have done to the collection. What am I missing ?
Thanks in advance to those who can help me.
If you need more information, feel free to ask.
In order to see modification on the fly in the grid too, Models.GamesProperties has to implemen properly INotifyPropertyChanged. Since you are using Caliburn, you probably want to derive it from PropertyChangedBase.

asp.net MVC - How to do a master/detail page

I wish to create a master/detail page. I see it working one of two ways:
Clicking a row in a grid calls the same page again with the addition of a details panel.
Clicking a row does javascript/JSON call to a controller action that returns details and populates a panel.
I would like the selected row to be highlighted. The selected row could be several pages into a paged grid.
Sounds easy. Unfortunately I'm new to asp.net MVC, and I'm not an experienced programmer. However, I can follow and adapt examples. I would appreciate examples of both the above methods to help me learn MVC.
Thanks in advance.
To answer my own question:
I ended up using PartialViews and jQuery.
Clicking on a select link against a row causes a new row to be added below the selected one (using jQuery). Into this row I use jQuery to GET /PurchaseOrder/Detail (a PartialView).
Here is my Javascript:
function GetDetails(id, enableEdit) {
var detailsRowExists = $().find("#detailsRow").size();
if (detailsRowExists) {
// Delete details row
// Note: need to rename id for row to be deleted
// because jQuery does not wait for the row to be
// deleted before adding the new row.
$("#detailsRow").attr("id", "detailsRowOld");
$("#detail").slideUp("normal", function() {
$("#detailsRowOld").remove();
});
};
// Put new row below selected one
$("tr[id=" + id + "]").after("<tr id='detailsRow'><td colspan='4'><div id='detail'><img src='../../Content/wait20trans.gif' />Loading...</div></td></tr>");
// Pull details into new row
$.get("/PurchaseOrder/Detail/" + id, { enableEdit: enableEdit },
function(data) {
$("#detail").hide();
$("#detail").html(data);
$("#detail").slideDown("normal");
}
);
}
Hopefully this may helps others trying to achieve a master/details page.

Resources