I'm working on a shopping Windows Phone 8.1 application, where I have a "Promotions" page. This page is a Pivot page with two PivotItems. The first Item shows the top 100 promotions, and the second Item shows all the promotions. To get the data I call a webservice. The data has the same structure in both cases, so I use the same ListView and DataTemplate on both pages. My question is: how can I avoid code duplication in this scenario? How can I use the same ListView and DataTemplate on the two PivotItems without copy-pasting XAML and code?
You need to create another property in your viewmodel that takes a filter of the first like this:
public ObservableCollection<ItemModel> ItemList { get; set; }
public IEnumerable<ItemModel> Top100List { get { return (from i in ItemList select i).Take(100); } }
Then bind each ListView to the appropriate property. This example assumes that the top 100 items are the first 100 items in the list. If they are not, then you will either have to modfy the linq statement or sort the list when adding items.
Related
I have a TreeViewer as shown here:
.
I have a text field to enter the percentage values. Suppose the percentage entered is 30 %, I should hide all the rows that are below 30% and display only the rows above 30%. Is there any row filter that I can use for my TreeViewer? It would be great if some examples are provided.
I am using e4 RCP. I want to do View based filtering and prefer not to change the Model.
You use a class which extends ViewFilter to filter the rows in a tree viewer.
The main method to override in the ViewFilter is the select method:
#Override
public boolean select(Viewer viewer, Object parentElement, Object element)
here you are given the object being considered (element) along with its parent and the viewer. You return true to keep displaying the element and false to hide it.
You can have several filters active if required, set them in the tree viewer using:
treeViewer.setFilters(array of view filters);
You may need to call
treeViewer.filter();
when something changes in the tree which requires the filters to be re-run.
I wrapped my gridview with Pjax widget like this
\yii\widgets\Pjax::begin();
gridview
\yii\widgets\Pjax::end();
in order to make the gridview make ajax request when I click on each pagination.
I also use ['class' => 'yii\grid\CheckboxColumn'], in column as well.
and I find that when I'm on first pagination I checked some rows and then go to second page and check some rows but when I go back to first page what I've checked is gone.
My question is how can I keep all checkedrow for all pagination
With current conditions (Pjax, multiple pages, yii\grid\CheckboxColumn) it's impossible because of the way it works.
When you click on the pagination links all GridView html content is replaced by new one that comes from the AJAX response.
So obviously all selected checkboxes on the previous page are gone.
Few possible ways to solve that:
1) Write custom javascript and server side logic.
As one of the options, you can send AJAX request to server with parameter meaning that user has chosen to select all data for the bulk delete operation (or use separate controller action for bulk deletion). In this case actually we don't need to get the selected data from user, because we can simply get them from database (credits - Seng).
2) Increase number of displayed rows per page.
3) Use infinite scroll extension, for example this.
4) Break desired action in several iterations:
select needed rows on first page, do action (for example, delete).
repeat this again for other pages.
You can get selected rows like that:
$('#your-grid-view').yiiGridView('getSelectedRows');
[infinite scroll] : http://kop.github.io/yii2-scroll-pager/ will work good if you do not have any pjax filters. If you have filters also in play, do not use this plugin as it does not support pjax filters with it. For rest of the applications it is perfect to use.
Update1 : it seems to be straight forward than expected, here is the how I accomplished it
Add following lines to the checkbox column
'checkboxOptions' => function($data){
return ['id' => $data->id, 'onClick' => 'selectedRow(this)'];
}
Now add following JS to the common js file you will have in your project of the page where this datagrid resides
var selectedItems=[]; //global variable
/**
* Store the value of the selected row or delete it if it is unselected
*
* #param {checkbox} ele
*/
function selectedRow(ele){
if($(ele).is(':checked')) {
//push the element
if(!selectedItems.includes($(ele).attr('id'))) {
selectedItems.push($(ele).attr('id'));
}
} else {
//pop the element
if(selectedItems.includes($(ele).attr('id'))) {
selectedItems.pop($(ele).attr('id'));
}
}
}
Above function will store the selected row ids in the global variable array
Now add following lines to pjax:end event handler
$(document).on('pjax:end', function () {
//Select the already selected items on the grid view
if(!empty(selectedItems)){
$.each(selectedItems, function (index,value) {
$("#"+value).attr('checked',true);
});
}
});
Hope it helps.
I just solved this problem and it works properly with Pjax.
You may use my CheckboxColumn. I hope this can help. The checked items are recorded with cookies.
You can read the part with //add by hezll to understand how to fix it, because I didn't provide a complete general one.
Hope it works for you.
https://owncloud.xiwangkt.com/index.php/s/dGH3fezC5MGCx4H
I'm trying to solve a problem. I am new to MVC and trying to understand how the models work. I get the main page and main model stuff and that if you want to show a partial view the data you show must be part of the main model. This makes the main model pretty large and doesn't that require me to submit the entire model to get the partial view? In any case, let's say I have a list of things and one column is a link. This link calls an AJAX method to get more data and display in a jQuery dialog - my goal. So I would have a call like this:
function showDetails(id) {
$("#divShowDetails").load('#(Url.Action("GetDetails", "Home", null, Request.Url.Scheme))?Id= ' + id);
}
My view is like "_DetailsView.cshtml", defined as a partial view. Does this page need to define the model in the main page or can it be a different model or no model at all? Can I return a ViewData from the controller method, pop open the dialog and fill it with data?
Should the controller method return a PartialViewResult or just an ActionResult? Let's say the details view are details of a part number or something and I want to show a bunch of data elements for the part. Does this have to me a model? I am confused and any help would be greatly appreciated.
Thanks guys. Do you still use the common:
[HttpGet]
public PartialViewResult SelectedItem (string itemId)
{
// gather data for the item
return PartialView(itemModel);
}
And you are saying that the itemModel does not have to be part of the item list model?
I am trying to implement an autocomplete field. The results are to be shown in a list. But everytime I make a search the new result is appended to the previous results. I tried clearing out the store attached to the list but it didn't work.
In debugger the store shows 2 items while the list shows many items (2 new + the items from previous search results)
Here is the fix:
list.refresh()
After removing the items from the attached store you need to refresh the list to tell it to load itself again.
try calling removeAll() on your store.
Eg.: Just to be sure check before removing
var isStoreLoaded =Ext.getStore("theStore").isLoaded( );
if(isStoreLoaded)
{
Ext.getStore("storeBomSearch").removeAll();
}
I hope this is a normal store, not a treeStore.
I have two related ComboBoxes ( continents, and countries ). When the continents ComboBox changes I request a XML from a certain URL. When I receive that XML i change the DataProvider for the countries ComboBox, like this:
public function displayCountryArray( items:XMLList ):void
{
this.resellersCountryLoader.alpha = 0;
this.resellersCountry.dataProvider = items;
this.resellersCountry.dispatchEvent( new ListEvent( ListEvent.CHANGE ) );
}
I dispatch the ListEvent.CHANGE because I use it to change another ComboBox so please ignore that (and the 1st line ).
So, my problem is this: I select "ASIA" from the first continents, then the combobox DATA get's updated ( I can see that because the first ITEM is an item with the label '23 countries' ). I click the combo then I can see the countries.
NOW, I select "Africa", the first item is displayed, with the ComboBox being closed, then when I click it, the countries are still the ones from Asia. Anyway, if I click an Item in the list, then the list updates correctly, and also, it has the correct info ( as I said it affects other ComboBoxes ). SO the only problem is that the display list does not get updated.
In this function I tried these approaches
Converting XMLList to XMLCollection and even ArrayCollection
Adding this.resellersCountry.invalidateDisplayList();
Triggering events like DATA_CHANGE and UPDATE_COMPLETE
I know they don't make much sense, but I got a little desperate.
Please note that when I used 3.0.0 SDK this did not happen.
Sorry if I'm stupid, but the flex events are killing me.
Setting the dataprovider of the comboBox' dropdown seems to fix this problem.
this.resellersCountry.dataProvider = items;
this.resellersCountry.dropdown.dataProvider = items;
this.resellersCountry.dropdown.dataProvider = items;
works (Flex SDK 3.5)
Hope this bug fixed in 4.0
In addition to Christophe´s answer:
When you are using data binding in your ComboBox you need to use the BindingUtils to set the dropdown´s dataprovider:
MXML:
<mx:ComboBox id="cb_fontFamily"
width="100%"
dataProvider="{ model.fontFamilies }" />
Script:
private function init():void
{
BindingUtils.bindSetter(updateFontFamilies, model, "fontFamilies");
}
private function updateFontFamilies(fontFamilies:ArrayCollection):void
{
if (cb_fontFamily != null) cb_fontFamily.dropdown.dataProvider = fontFamilies;
}
Thanks to Christophe for pointing in the right direction.
Another workaround, outlined in an Adobe Community forum post, is to avoid re-assigning a different ArrayCollection object to the ComboBox, and instead re-using (and re-populating) the original one instead:
items.removeAll();
for each (var item:* in newItems)
{
items.addItem(item);
}