Related
I've taken over the code from another developer, and I'm quite confused and stuck: one controller I can call the class method CLASSS::method perfectly OK. the other Controller has a copy of the orginal code and modified. On the second one, I get the "non-static method" error.
Call Chain:
Controller->Class->filtered results->Controller response
1A) (Working) Conttroller
<?php
namespace App\Http\Controllers\V1;
use App\Site as SiteClass;
use Facades\App\Site;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\Request;
use App\{
Http\Controllers\Controller,
Http\Requests\SiteRequest,
Helper\ResourceTrait,
Assets,
Alerts,
Licensee,
Permits,
LandOwner,
Utility
};
use Illuminate\Support\Collection;
class SiteController extends Controller
{
private $obj;
public function __construct()
{
$this->obj = new SiteClass();
}
public function index(Request $request)
{
try
{
$data = Site::filter(
($request->has('sort')? $request->input('sort') : ''),
($request->has('filter')? $request->input('filter') : '')
);
...removed some extra code that's not relevant ...
return response($data);
}
catch(\Exception $e)
{
Log::info('Create exception from here?' . $e);
return response(array('error'=>$e->getMessage()),422);
}
} // index
....
}
1B) (Working) Class
<?php
namespace App;
use Illuminate\Support\Facades\Config;
use \App\BaseModel;
class Site extends BaseModel
{
protected $table = 'sites';
protected $fillable = [
"status","structureType","siteId","name","coverage","address","postCode", "subdistrict", "district", "region", "state", "country", "localCouncil", "latitude", "longitude", "dimensions",
"siteHandover", "startBilling", "utilityBillAcct", "utilityBillingAddress", "renewalTerm",
"capex", "opex", "siteManager", "siteManagerPhone", "siteManagerEmail", "siteOwnerManager", "siteOwnerManagerPhone", "siteOwnerManagerEmail"
];
...
// Working Static method call.
public function filter($sort = null, $search = null)
{
$data = $this;
// check if search variable not empty
if ($search != null)
{
$data = $data->where(function ($query) use ($search){
return $query->where($this->table.'.name','like','%'.$search.'%')
->orWhere($this->table.'.status','=',$search)
->orWhere($this->table.'.siteId','like','%'.$search.'%')
->orWhere($this->table.'.address','like','%'.$search.'%')
->orWhere($this->table.'.subdistrict','like','%'.$search.'%')
->orWhere($this->table.'.district','like','%'.$search.'%')
->orWhere($this->table.'.region','like','%'.$search.'%')
->orWhere($this->table.'.state','like','%'.$search.'%')
->orWhere($this->table.'.country','like','%'.$search.'%')
->orWhere($this->table.'.localCouncil','like','%'.$search.'%')
;
});
if ($sort != null)
{
$sorts = explode('|', $sort);
$data = $data->orderBy($sorts[0],$sorts[1]);
}
}
// check if sort variable not empty
if ($sort != null)
{
$sorts = explode('|', $sort);
$data = $data->orderBy($sorts[0],$sorts[1]);
}
else
{
$data = $data->orderBy('siteId','desc');
}
// return data
return $data->paginate(Config::get('api.records'));
}
}
2A) (Failing) Controller
<?php
namespace App\Http\Controllers\V1;
use App\{
Http\Controllers\Controller,
Helper\ResourceTrait,
Http\Requests\OrganisationRequest,
Organisation
};
use Illuminate\{
Http\Request,
Support\Facades\Config,
Support\Facades\Log
};
class OrganisationController extends Controller
{
private $org;
public function __construct()
{
$this->org = new Organisation();
}
public function index(Request $request)
{
try
{
//WORKAROUND: $this->org->... works
$data = Organisation::filter(
($request->has('sort')? $request->input('sort') : ''),
($request->has('filter')? $request->input('filter') : '')
); // FAILS with non-static method call error
return response($data);
}
catch(\Exception $e)
{
return response(array('error'=>$e->getMessage()),422);
}
} // index
}
...
2B) Failing Class
<?php
namespace App;
use Illuminate\Support\Facades\Config;
use \App\BaseModel;
class Organisation extends BaseModel
{
protected $table = 'organisation';
public function filter($sort = null, $search = null)
{
$data = $this;
// check if search variable not empty
if ($search != null)
{
$data = $data->where(function ($query) use ($search){
return $query->where($this->table.'.name','like','%'.$search.'%')
;
});
if ($sort != null)
{
$sorts = explode('|', $sort);
$data = $data->orderBy($sorts[0],$sorts[1]);
}
}
// check if sort variable not empty
if ($sort != null)
{
$sorts = explode('|', $sort);
$data = $data->orderBy($sorts[0],$sorts[1]);
}
else
{
$data = $data->orderBy('name');
}
// return data
return $data->paginate(Config::get('api.records'));
}
}
To my untutored eye, they look identical, yet one works and the other doesn't. Apologies in advance for the volume of code, but I don't know which parts are affecting what. I suspect it's somethng to do with an imported class, but I'm lost frankly :-D
Site has a Facade while Organisation does not.
Facades (from the docs) provide a "static" interface to classes that are available in the application's service container.
I've written an CustomResourceHandler to add a version number to my js and css files, which works fine, but all primefaces resources get a double version number now.
Without CustomResourceHandler:
javax.faces.resource/jquery/jquery-plugins.js.xhtml?ln=primefaces&v=6.0.17
With CustomResourceHandler:
javax.faces.resource/jquery/jquery-plugins.js.xhtml?ln=primefaces&v=6.0.17&v=6.0.17
My CustomResourceHandler:
public class ExtendedResourceHandler extends PrimeResourceHandler {
public ExtendedResourceHandler(ResourceHandler wrapped) {
super(wrapped);
}
#Override
public Resource createResource(String resourceName, String libraryName) {
if (!org.primefaces.util.Constants.LIBRARY.equalsIgnoreCase(libraryName)
&& !org.primefaces.extensions.util.Constants.LIBRARY.equalsIgnoreCase(libraryName) && !"javax.faces".equalsIgnoreCase(libraryName) && resourceName != null
&& (resourceName.endsWith(".css") || resourceName.endsWith(".js"))) {
final Resource resource = super.createResource(resourceName, libraryName);
if (resource == null) {
return null;
}
return new ResourceWrapper() {
#Override
public String getRequestPath() {
String resultPath = super.getRequestPath();
resultPath += (resultPath.contains("?") ? "&" : "?") + "version=V6326";
return resultPath;
}
#Override
public Resource getWrapped() {
return resource;
}
};
} else {
return super.createResource(resourceName, libraryName);
}
}
}
faces-config.xml:
<resource-handler>de.sync4.cockpit.web.beans.resourcehandler.ExtendedResourceHandler</resource-handler>
Because of that problem I can't get the pe:ckEditor to work, because it can't find necessary resources. Any idea what's wrong with my Handler?
Found the Problem. I needed to extend the ResourceHandlerWrapper, not the PrimeResourceHandler.
I also have an ExtendedBeanELResolver. I had to return null there if the base object is an instance of my custom handler.
In PrimeFaces 5.0, datatable filter is case sensitive. In Primefaces 4 the filter was not case sensitive. But now in 5.0 my app doesn't work.
DataTable Filtering v. 5.0.1
Filtering is case sensitive in 5.0, due to feedback it is now case insensitive. FilterEvent was also providing wrong information about the filters, it has been corrected as well.
http://blog.primefaces.org/?p=3184
You can use the filterFunction option, like this:
In XHTML:
<p:column ...
filterBy="#{car.name}"
filterFunction="#{carListView.filterByName}"
In View:
public boolean filterByName(Object value, Object filter, Locale locale) {
String filterText = (filter == null) ? null : filter.toString().trim();
if (filterText == null || filterText.equals("")) {
return true;
}
if (value == null) {
return false;
}
String carName = value.toString().toUpperCase();
filterText = filterText.toUpperCase();
if (carName.contains(filterText)) {
return true;
} else {
return false;
}
}
This worked for me. Please refer to: http://www.primefaces.org/showcase/ui/data/datatable/filter.xhtml (price column). And also page 153 at the PrimeFaces 5.0 manual (pdf).
I have been facing the same problem.
But I fix it replacing the filter class of primefaces.
1- create a package in you project: org.primefaces.component.datatable.feature
2 - create a class: FilterFeature
I've included this part on the class:
// FIX bug primefaces 5.0
// The filter should be case insensitive
if(columnValue != null && filterValue!= null){
columnValue = columnValue.toString().toUpperCase();
filterValue = filterValue.toString().toUpperCase();
}
Copy the contents of this class to your file.
FilterFeature.java
/*
* Copyright 2009-2014 PrimeTek.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.primefaces.component.datatable.feature;
import java.io.IOException;
import java.util.*;
import java.util.logging.Level;
import java.util.logging.Logger;
import javax.el.ELContext;
import javax.el.MethodExpression;
import javax.el.ValueExpression;
import javax.faces.FacesException;
import org.primefaces.component.api.UIColumn;
import javax.faces.component.UIComponent;
import javax.faces.component.UINamingContainer;
import javax.faces.component.ValueHolder;
import javax.faces.context.FacesContext;
import org.primefaces.component.api.DynamicColumn;
import org.primefaces.component.column.Column;
import org.primefaces.component.columngroup.ColumnGroup;
import org.primefaces.component.datatable.DataTable;
import org.primefaces.component.datatable.DataTableRenderer;
import org.primefaces.component.row.Row;
import org.primefaces.context.RequestContext;
import org.primefaces.model.filter.*;
import org.primefaces.util.Constants;
public class FilterFeature implements DataTableFeature {
private final static Logger logger = Logger.getLogger(DataTable.class.getName());
private final static String STARTS_WITH_MATCH_MODE = "startsWith";
private final static String ENDS_WITH_MATCH_MODE = "endsWith";
private final static String CONTAINS_MATCH_MODE = "contains";
private final static String EXACT_MATCH_MODE = "exact";
private final static String LESS_THAN_MODE = "lt";
private final static String LESS_THAN_EQUALS_MODE = "lte";
private final static String GREATER_THAN_MODE = "gt";
private final static String GREATER_THAN_EQUALS_MODE = "gte";
private final static String EQUALS_MODE = "equals";
private final static String IN_MODE = "in";
private final static String GLOBAL_MODE = "global";
final static Map<String,FilterConstraint> FILTER_CONSTRAINTS;
static {
FILTER_CONSTRAINTS = new HashMap<String,FilterConstraint>();
FILTER_CONSTRAINTS.put(STARTS_WITH_MATCH_MODE, new StartsWithFilterConstraint());
FILTER_CONSTRAINTS.put(ENDS_WITH_MATCH_MODE, new EndsWithFilterConstraint());
FILTER_CONSTRAINTS.put(CONTAINS_MATCH_MODE, new ContainsFilterConstraint());
FILTER_CONSTRAINTS.put(EXACT_MATCH_MODE, new ExactFilterConstraint());
FILTER_CONSTRAINTS.put(LESS_THAN_MODE, new LessThanFilterConstraint());
FILTER_CONSTRAINTS.put(LESS_THAN_EQUALS_MODE, new LessThanEqualsFilterConstraint());
FILTER_CONSTRAINTS.put(GREATER_THAN_MODE, new GreaterThanFilterConstraint());
FILTER_CONSTRAINTS.put(GREATER_THAN_EQUALS_MODE, new GreaterThanEqualsFilterConstraint());
FILTER_CONSTRAINTS.put(EQUALS_MODE, new EqualsFilterConstraint());
FILTER_CONSTRAINTS.put(IN_MODE, new InFilterConstraint());
FILTER_CONSTRAINTS.put(GLOBAL_MODE, new GlobalFilterConstraint());
}
private boolean isFilterRequest(FacesContext context, DataTable table) {
return context.getExternalContext().getRequestParameterMap().containsKey(table.getClientId(context) + "_filtering");
}
public boolean shouldDecode(FacesContext context, DataTable table) {
return false;
}
public boolean shouldEncode(FacesContext context, DataTable table) {
return isFilterRequest(context, table);
}
public void decode(FacesContext context, DataTable table) {
String globalFilterParam = table.getClientId(context) + UINamingContainer.getSeparatorChar(context) + "globalFilter";
List<FilterMeta> filterMetadata = this.populateFilterMetaData(context, table);
Map<String,Object> filterParameterMap = this.populateFilterParameterMap(context, table, filterMetadata, globalFilterParam);
table.setFilters(filterParameterMap);
table.setFilterMetadata(filterMetadata);
}
public void encode(FacesContext context, DataTableRenderer renderer, DataTable table) throws IOException {
//reset state
updateFilteredValue(context, table, null);
table.setFirst(0);
table.setRowIndex(-1);
if(table.isLazy()) {
table.loadLazyData();
}
else {
String globalFilterParam = table.getClientId(context) + UINamingContainer.getSeparatorChar(context) + "globalFilter";
filter(context, table, table.getFilterMetadata(), globalFilterParam);
//sort new filtered data to restore sort state
boolean sorted = (table.getValueExpression("sortBy") != null || table.getSortBy() != null);
if(sorted) {
SortFeature sortFeature = (SortFeature) table.getFeature(DataTableFeatureKey.SORT);
if(table.isMultiSort())
sortFeature.multiSort(context, table);
else
sortFeature.singleSort(context, table);
}
}
renderer.encodeTbody(context, table, true);
}
private void filter(FacesContext context, DataTable table, List<FilterMeta> filterMetadata, String globalFilterParam) {
Map<String,String> params = context.getExternalContext().getRequestParameterMap();
List filteredData = new ArrayList();
Locale filterLocale = table.resolveDataLocale();
boolean hasGlobalFilter = params.containsKey(globalFilterParam);
String globalFilterValue = hasGlobalFilter ? params.get(globalFilterParam): null;
GlobalFilterConstraint globalFilterConstraint = (GlobalFilterConstraint) FILTER_CONSTRAINTS.get(GLOBAL_MODE);
ELContext elContext = context.getELContext();
for(int i = 0; i < table.getRowCount(); i++) {
table.setRowIndex(i);
boolean localMatch = true;
boolean globalMatch = false;
for(FilterMeta filterMeta : filterMetadata) {
Object filterValue = filterMeta.getFilterValue();
UIColumn column = filterMeta.getColumn();
MethodExpression filterFunction = column.getFilterFunction();
ValueExpression filterByVE = filterMeta.getFilterByVE();
if(column instanceof DynamicColumn) {
((DynamicColumn) column).applyStatelessModel();
}
Object columnValue = filterByVE.getValue(elContext);
FilterConstraint filterConstraint = this.getFilterConstraint(column);
// FIX bug primefaces 5.0
// The filter should be case insensitive
if(columnValue != null && filterValue!= null){
columnValue = columnValue.toString().toUpperCase();
filterValue = filterValue.toString().toUpperCase();
}
if(hasGlobalFilter && !globalMatch) {
globalMatch = globalFilterConstraint.applies(columnValue, globalFilterValue, filterLocale);
}
if(filterFunction != null) {
localMatch = (Boolean) filterFunction.invoke(elContext, new Object[]{columnValue, filterValue, filterLocale});
}
else if(!filterConstraint.applies(columnValue, filterValue, filterLocale)) {
localMatch = false;
}
if(!localMatch) {
break;
}
}
boolean matches = localMatch;
if(hasGlobalFilter) {
matches = localMatch && globalMatch;
}
if(matches) {
filteredData.add(table.getRowData());
}
}
//Metadata for callback
if(table.isPaginator()) {
RequestContext requestContext = RequestContext.getCurrentInstance();
if(requestContext != null) {
requestContext.addCallbackParam("totalRecords", filteredData.size());
}
}
//save filtered data
updateFilteredValue(context, table, filteredData);
table.setRowIndex(-1); //reset datamodel
}
public void updateFilteredValue(FacesContext context, DataTable table, List<?> value) {
table.setSelectableDataModelWrapper(null);
ValueExpression ve = table.getValueExpression("filteredValue");
if(ve != null) {
ve.setValue(context.getELContext(), value);
}
else {
if(value != null) {
logger.log(Level.WARNING, "DataTable {0} has filtering enabled but no filteredValue model reference is defined"
+ ", for backward compatibility falling back to page viewstate method to keep filteredValue."
+ " It is highly suggested to use filtering with a filteredValue model reference as viewstate method is deprecated and will be removed in future."
, new Object[]{table.getClientId(context)});
}
table.setFilteredValue(value);
}
}
private Map<String,Object> populateFilterParameterMap(FacesContext context, DataTable table, List<FilterMeta> filterMetadata, String globalFilterParam) {
Map<String,String> params = context.getExternalContext().getRequestParameterMap();
Map<String,Object> filterParameterMap = new HashMap<String, Object>();
for(FilterMeta filterMeta : filterMetadata) {
Object filterValue = filterMeta.getFilterValue();
UIColumn column = filterMeta.getColumn();
if(filterValue != null && !filterValue.toString().trim().equals(Constants.EMPTY_STRING)) {
String filterField = null;
ValueExpression filterByVE = column.getValueExpression("filterBy");
if(column.isDynamic()) {
((DynamicColumn) column).applyStatelessModel();
Object filterByProperty = column.getFilterBy();
String field = column.getField();
if(field == null)
filterField = (filterByProperty == null) ? table.resolveDynamicField(filterByVE) : filterByProperty.toString();
else
filterField = field;
}
else {
String field = column.getField();
if(field == null)
filterField = (filterByVE == null) ? (String) column.getFilterBy(): table.resolveStaticField(filterByVE);
else
filterField = field;
}
filterParameterMap.put(filterField, filterValue);
}
}
if(params.containsKey(globalFilterParam)) {
filterParameterMap.put("globalFilter", params.get(globalFilterParam));
}
return filterParameterMap;
}
private List<FilterMeta> populateFilterMetaData(FacesContext context, DataTable table) {
List<FilterMeta> filterMetadata = new ArrayList<FilterMeta>();
String separator = String.valueOf(UINamingContainer.getSeparatorChar(context));
String var = table.getVar();
Map<String,String> params = context.getExternalContext().getRequestParameterMap();
ColumnGroup group = getColumnGroup(table, "header");
if(group != null) {
for(UIComponent child : group.getChildren()) {
Row headerRow = (Row) child;
if(headerRow.isRendered()) {
for(UIComponent headerRowChild : headerRow.getChildren()) {
Column column = (Column) headerRowChild;
if(column.isRendered()) {
ValueExpression columnFilterByVE = column.getValueExpression("filterBy");
Object filterByProperty = column.getFilterBy();
if(columnFilterByVE != null || filterByProperty != null) {
ValueExpression filterByVE = (columnFilterByVE != null) ? columnFilterByVE : createFilterByVE(context, var, filterByProperty);
UIComponent filterFacet = column.getFacet("filter");
Object filterValue;
if(filterFacet == null)
filterValue = params.get(column.getClientId(context) + separator + "filter");
else
filterValue = ((ValueHolder) filterFacet).getLocalValue();
filterMetadata.add(new FilterMeta(column, filterByVE, filterValue));
}
}
}
}
}
}
else {
for(UIColumn column : table.getColumns()) {
ValueExpression columnFilterByVE = column.getValueExpression("filterBy");
Object filterByProperty = column.getFilterBy();
if (columnFilterByVE != null || filterByProperty != null) {
UIComponent filterFacet = column.getFacet("filter");
Object filterValue = null;
ValueExpression filterByVE = null;
String filterId = null;
if(column instanceof Column) {
filterByVE = (columnFilterByVE != null) ? columnFilterByVE : createFilterByVE(context, var, filterByProperty);
filterId = column.getClientId(context) + separator + "filter";
}
else if(column instanceof DynamicColumn) {
DynamicColumn dynamicColumn = (DynamicColumn) column;
dynamicColumn.applyStatelessModel();
filterByProperty = column.getFilterBy();
filterByVE = (filterByProperty == null) ? columnFilterByVE : createFilterByVE(context, var, filterByProperty);
filterId = dynamicColumn.getContainerClientId(context) + separator + "filter";
dynamicColumn.cleanStatelessModel();
}
if(filterFacet == null)
filterValue = params.get(filterId);
else
filterValue = ((ValueHolder) filterFacet).getLocalValue();
filterMetadata.add(new FilterMeta(column, filterByVE, filterValue));
}
}
}
return filterMetadata;
}
private ColumnGroup getColumnGroup(DataTable table, String target) {
for(UIComponent child : table.getChildren()) {
if(child instanceof ColumnGroup) {
ColumnGroup colGroup = (ColumnGroup) child;
String type = colGroup.getType();
if(type != null && type.equals(target)) {
return colGroup;
}
}
}
return null;
}
public FilterConstraint getFilterConstraint(UIColumn column) {
String filterMatchMode = column.getFilterMatchMode();
FilterConstraint filterConstraint = FILTER_CONSTRAINTS.get(filterMatchMode);
if(filterConstraint == null) {
throw new FacesException("Illegal filter match mode:" + filterMatchMode);
}
return filterConstraint;
}
private ValueExpression createFilterByVE(FacesContext context, String var, Object filterBy) {
ELContext elContext = context.getELContext();
return context.getApplication().getExpressionFactory().createValueExpression(elContext, "#{" + var + "." + filterBy + "}", Object.class);
}
private class FilterMeta {
private UIColumn column;
private ValueExpression filterByVE;
private Object filterValue;
public FilterMeta(UIColumn column, ValueExpression filterByVE, Object filterValue) {
this.column = column;
this.filterByVE = filterByVE;
this.filterValue = filterValue;
}
public UIColumn getColumn() {
return column;
}
public ValueExpression getFilterByVE() {
return filterByVE;
}
public Object getFilterValue() {
return filterValue;
}
}
}
I took a little more simplistic approach to get past this in my situation.
In my XHTML:
<p:column filterBy="#{car.nameLowercase}" sortBy="#{car.name}"
filterMatchMode="contains">
<h:outputText value="#{car.name}"/>
</p:column>
In my car bean I simply add a getter:
public String getNameLowerCase() {
if (name == null) {
return null;
}
return name.toLowerCase();
}
This seems to work for my purposes. Hope it will help you!
I had same issue on the Lazy.xhtml, I fixied it by go to the LazyCarDataModel.java, on load method, change
if(filterValue==null ||
fieldvalue.startswith(filtervalue.toString()))
to
if(filterValue==null ||
fieldvalue.startswith(filtervalue.toString().toLowerCase() ||
fieldvalue.startswith(filtervalue.toString().toUpperCase()) )
It appears that filtering an ObservableCollection with CollectionViewSource is not possible in WinRT:
See here!
I can filter using LINQ, but how do I get the UI to update if changes that affect the filtered data are made?
I ended up writing my own class to achieve the desired effect:
public class ObservableCollectionView<T> : ObservableCollection<T>
{
private ObservableCollection<T> _view;
private Predicate<T> _filter;
public ObservableCollectionView(IComparer<T> comparer)
: base(comparer)
{
}
public ObservableCollectionView(IComparer<T> comparer, IEnumerable<T> collection)
: base(comparer, collection)
{
}
public ObservableCollectionView(IComparer<T> comparer, IEnumerable<T> collection, Predicate<T> filter)
: base(comparer, collection == null ? new T[] { } : collection)
{
if (filter != null)
{
_filter = filter;
if (collection == null)
_view = new ObservableCollection<T>(comparer);
else
_view = new ObservableCollection<T>(comparer, collection);
}
}
public ObservableCollection<T> View
{
get
{
return (_filter == null ? this : _view);
}
}
public Predicate<T> Filter
{
get
{
return _filter;
}
set
{
if (value == null)
{
_filter = null;
_view = new ObservableCollection<T>(Comparer);
}
else
{
_filter = value;
Fill();
}
}
}
private void Fill()
{
_view = new ObservableCollection<T>(Comparer);
foreach (T item in this)
{
if (Filter(item))
View.Add(item);
}
}
private int this[T item]
{
get
{
int foundIndex = -1;
for (int index = 0; index < View.Count; index++)
{
if (View[index].Equals(item))
{
foundIndex = index;
break;
}
}
return foundIndex;
}
}
protected override void OnCollectionChanged(NotifyCollectionChangedEventArgs e)
{
base.OnCollectionChanged(e);
if (_filter != null)
{
switch (e.Action)
{
case NotifyCollectionChangedAction.Add:
foreach (T item in e.NewItems)
if (Filter(item))
View.Add(item);
break;
case NotifyCollectionChangedAction.Move:
break;
case NotifyCollectionChangedAction.Remove:
foreach (T item in e.OldItems)
if (Filter(item))
View.Remove(item);
break;
case NotifyCollectionChangedAction.Replace:
for (int index = 0; index < e.OldItems.Count; index++)
{
T item = (T)e.OldItems[index];
if (Filter(item))
{
int foundIndex = this[item];
if (foundIndex != -1)
View[foundIndex] = (T)e.NewItems[index];
}
}
break;
case NotifyCollectionChangedAction.Reset:
Fill();
break;
}
}
}
protected override void OnPropertyChanged(PropertyChangedEventArgs e)
{
base.OnPropertyChanged(e);
if (_filter != null)
{
// TODO: Implement code for property changes
}
}
}
Not yet perfect. So improvements/suggestions welcomed.
You can now bind this object, directly to a control using the View property.
You need to make sure the filtering changes are observable, so you can set the source of the CollectionViewSource to an ObservableCollection and make the changes on that collection or assign a new Source of the CVS to a new, filtered collection.
interface If { ... }
class Impl implements If { ... }
function test(type:Class, obj) {
return obj instanceof type;
}
test(If, new Impl());
The call to test on the last line returns false, but it should be true. How can I do this check right, with the requirement that it must be inside the function?
Real code:
public function iterate(callback:Function, type:Class = null) {
for (var node:EntityListNode = beginNode; node != null; node = node.next) {
if (type == null || node.entity instanceof type) callback(node.entity);
}
}
if(Object is IInterface) ... works fine for that AFAIK.