When it comes to Comboboxes/Drop-down lists so there are so many different ways to set them up and use them. It mostly comes down to preference of how you want your UI to look and operate.
Just setting them to directly use the "lookup table" or "data table" or whatever you are basing the filter on is by far one of the easiest ways but with that ease comes very limited flexibility. The VFP control doesn't natively provide a simple way to just set one or two properties on the control to have an item in the list that is obviously, to the user, the equivalent of a "No filter" option but it does provide options for you to add one yourself.
If I'm building a filter drop-down like you've described and the number of options isn't going to be in the multiple hundreds or thousands then one of my preferences is to use RowSourceType 3 - SQL Statement OR 2 - Alias and write my own query to pull out the items, in the format that I want to, and this provides easy ways of adding any kind of custom "empty" or "no filter" item into that solution.
For example, let say I'm using the Northwind Employees table as the source for my drop-down filter. I can run a query such as:
Code:
Select Cast("<All Employees>" AS C(40)) AS FullName ,Cast(0 As I) As EmployeeId From Employees Where EmployeeId = 1 Union Select Cast(Alltrim(LastName) + ", " + Alltrim(FirstName) AS C(40)) As Fullname ,EmployeeId From Employees Order By 1 Into Cursor ddEmployee
...and this will give me a list of all the employees, but with a <All Employees> item at the top of the list. The default item will have an ID of zero and all the rest of the items will have their correct Employee ID. This will allow me to code the logic on the UI to say if the value of the drop-down is greater than zero, apply the filter, otherwise ignore the filter.
NOTE: One less than ideal aspect of that particular query is that for the <All Employees> item in that SQL query, I had to code WHERE EmployeeId = 1, to ensure that I did get 1 and only 1 item. I did that because I'd looked at the Employees table and I knew it had a row where EmployeeId = 1 so it worked for my example but in an empty database or one where ID #1 doesn't exist for another reason, like it has been deleted due it the table not being a static lookup, that WHERE clause would not work to give you the desired item. To make that part always work all of the time you could pull using a table where you can guarantee a particular row exists, in most of my applications we do always have one "company" record or "instance" record that stores some configuration for the installation so we can use that but you can also use a concept that some people do in their databases and that is to have a simple numbers table or cursor. This can take a number of forms but in it's simplest terms it could just be a cursor with maybe just ten records in it where the IDs for each row are the numbers 1 to 10 and have it so your application can always call upon this table if it ever needs to. You can use this table/cursor for lots of useful things and one is for this type of solution:
Code:
Select Cast("<All Employees>" AS C(40)) AS FullName ,Cast(0 As I) As EmployeeId From MyNumber Where Id = 1 Union Select Cast(Alltrim(LastName) + ", " + Alltrim(FirstName) AS C(40)) As Fullname ,EmployeeId From Employees Order By 1 Into Cursor ddEmployee
That will create the <All Employees> item using the number cursor and union in the employees from the employees table.
Another option is to specifically use SELECT TOP 1 in that part that is creating the <All Employees> item but you'd still have to be sure the table you have in your FROM has at least 1 row.
In full SQL Server these hacks for that item are not required, in SQL Server these days (and for a long time) you can just do the equivalent of:
Code:
Select Cast("<All Employees>" AS C(40)) AS FullName ,Cast(0 As I) As EmployeeId Union Select Cast(Alltrim(LastName) + ", " + Alltrim(FirstName) AS C(40)) As Fullname ,EmployeeId From Employees Order By 1 Into Cursor ddEmployee
...ignoring the fact that some of that is VFP syntax, it's a bit of a mish mash, I'm just demoing that in other database engines you can remove the FROM and WHERE from the first part and it'll just create one row with the specified values. VFP requires a FROM and the FROM dictates how many rows in conjunction with WHERE and JOINs etc.
This means another potential solution is to pre-emptively create your own separate cursor/alias with the contents that you want in the drop down. For example you could write code in the LOAD event of your form to create a cursor, insert the "default" row with whatever values you want and then append in the rows for the filters. Still continuing with the Northwind Employees example:
Code:
Create Cursor MyFilter (FullName C(40), Id I)
Insert Into MyFilter (FullName, Id) VALUES ("<All Employees>", 0)
Insert Into MyFilter (FullName, Id) SELECT Alltrim(LastName) + ", " + Alltrim(FirstName) As Fullname, EmployeeId From Employees Order By 1
With the cursor created with the exact contents that you want, you can use RowSourceType 2 - Alias or 6 - Fields and the appropriate RowSource
Some of these solutions will leave cursors/aliases sat in the background so be mindful of that and, if necessary, tidy them up by closing them in the UNLOAD method of your form.
These are just a few suggestions, when it comes to combos and drop-downs there are no right answers just many alternative answers.