In Delphi I have an own class which is based on TList. It is TPetList. Every instance of TPetList can have some items of the class TPet. The instance of TPetList is displayed in a TListView component using a for loop.
TPet is based on TObject and has the following fields:
- city
- age
- breed
Now I have a list of checkboxes where the user can tick the breeds he wants to see. So if he only wants to see pets of breed XYZ I want to show only entries which have the value of "breed" set to "XYZ" while the order in TPetList and TListView must remain the same.
How can I do this?
If I delete the items in TPetList 开发者_StackOverflow社区and show the rest in TListView, everything's fine until the user wants to see another breed. This breed has been deleted before and can't be showed.
Instead of deleting, try selecting out a new list. Something like this:
function TPetList.Filter(criteria: TPetCriteria): TPetList;
var
i: integer;
begin
result := TPetList.Create;
for i := 0 to self.Count - 1 do
if criteria.matches(self[i]) then
result.add(self[i]);
end;
How you implement the criteria is up to you, but that's the general idea. Remember that the list this returns is a sub-view and does not own the items it contains, so don't free them when you free the filtered list.
You can store your objects in a data set. (You can use memory datasets like TClientDataSet, JVCL's TjvMemoryData or any other TDataSet descendant including full-blown RDBMS)
In this way you have solved the following problems:
- Persistence (storage) - your RDBMS will take care of that. In the case of memory datasets you have methods like Load/SaveToFile
- Sort - There are simple methods to do this or if you'll choose a SQL backend a simple
'SELECT * FROM PETS ORDER BY NAME'
will do your job - Filter - you can do any reversible filtering on any field with any operator you like. In the case of memory datasets setting the
Filter
property to Breed="foo" and theFiltered
property to 'True' is enough. In the case of RDBMSes you can achieve it in the same way and/or using a standard SQL:'SELECT * FROM PETS WHERE BREED='foo' ORDER BY NAME
. Also you can useOnFilterRecord
event for that. Of course you can clear the filter, reversing the action: Setting theFilter
property to 'False' - or - issuing an SQL like:'SELECT * FROM PETS'
(without the WHERE clause) etc. - Editing - you have dedicated controls for each data type (including grids for multi-row input). Eg. for the 'Age' field the input is restricted to numbers only. And, of course, you have the
OnValidate
event where you can do a test if 'Age' is between 0 and 33 (for example).
You have all the mechanism in place. Perhaps is better to go on this path rather than to reinvent the wheel.
精彩评论