Next we show how to perform several different queries and display the results in a DataGridView
. This app only reads data from the entity data model, so we disabled the buttons in the BindingNavigator
that enable the user to add and delete records—simply select each button and set its Enabled property to False
in the Properties window. You also could delete these buttons from the BindingNavigator
. Later, we’ll explain why we do not support modifying the database in this example.
The Display Query Results app (Figs. 22.23–22.25) allows the user to select a query from the ComboBox
at the bottom of the window, then displays the results of the query.
Perform the following steps to build the Display Query Results app’s GUI.
Perform the steps in Section 22.5.2 to create a new Windows Forms Application project named DisplayQueryResult
in the same solution as the DisplayTable
app. Rename the Form1.cs
source file to TitleQueries.cs
. Set the Form
’s Text property to Display
Query Results
. Be sure to add references to the BooksExamples
and EntityFramework
libraries, add the connection string to the project’s App.Config
file and set the DisplayQuery-Result
project as the startup project.
DataGridView
to Display the Titles
TableFollow Steps 1 and 2 in Section 22.5.3 to create the data source and the DataGridView
. For this example, select the Title
class (rather than Author
) as the data source, and drag the Title node from the Data Sources window onto the form. Remove the Authors
column from the DataGridView
, as it will not be used in this example.
ComboBox
to the Form
In Design view, add a ComboBox
named queriesComboBox
below the DataGridView
on the Form
. Users will select which query to execute from this control. Set the ComboBox
’s Dock
property to Bottom
and the DataGridView
’s Dock
property to Fill
.
Next, you’ll add the names of the queries to the ComboBox
. Open the ComboBox
’s String Collection Editor by right clicking the ComboBox
and selecting Edit Items…. You also can access the String Collection Editor from the ComboBox
’s smart tag menu. A smart tag menu provides you with quick access to common properties you might set for a control (such as the Multiline
property of a TextBox
), so you can set these properties directly in Design view, rather than in the Properties window. You can open a control’s smart tag menu by clicking the small arrowhead
that appears in the control’s upper-right corner in Design view when the control is selected. In the String Collection Editor, add the following three items to queriesComboBox
— one for each of the queries we’ll create:
All titles
Titles with 2016 copyright
Titles ending with “How to Program”
Next you’ll create the code for this app (Fig. 22.26).
Form
’s Load
Event HandlerCreate the TitleQueries_Load
event handler (lines 22–29) by double clicking the title bar in Design view. When the Form
loads, it should display the complete list of books from the Titles
table, sorted by title. Line 24 calls the Load
extension method on the BookEntities DbContext
’s Titles
property to load the Titles
table’s contents into memory. Rather than defining the same LINQ query as in lines 40–41, we can programmatically cause the queriesComboBox_SelectedIndexChanged
event handler to execute simply by setting the queriesComboBox
’s SelectedIndex
to 0
(line 28).
queriesComboBox_SelectedIndexChanged
Event HandlerNext you must write code that executes the appropriate query each time the user chooses a different item from queriesComboBox
. Double click queriesComboBox
in Design view to generate a queriesComboBox_SelectedIndexChanged
event handler (lines 32–63) in the TitleQueries.cs
file. In the event handler, add a switch
statement (lines 36–60). Each case
in the switch
will change the titleBindingSource
’s DataSource
property to the results of a query that returns the correct set of data. The data bindings created by the IDE automatically update the titleDataGridView
each time we change its DataSource
. The BindingSource
maintains a Position
property that represents the current item in the data source. The MoveFirst
method of the BindingSource
(line 62) sets the Position
property to 0
to move to the first row of the result each time a query executes. The results of the queries in lines 40–41, 46–49 and 54–58 are shown in Figs. 22.23–22.25, respectively. Because we do not modify the data in this app, each of the queries is performed on the in-memory representation of the Titles
table, which is accessible through dbcontext.Titles.Local
.
Lines 40–41 invoke the OrderBy
extension method on dbcontext.Titles.Local
to order the Title
objects by their Title1
property values. As we mentioned previously, the IDE renamed the Title
column of the database’s Titles
table as Title1
in the generated Title
entity data model class to avoid a naming conflict with the class’s name. Recall that Local
returns an ObservableCollection<T>
containing the row objects of the specified table—in this case, Local
returns an ObservableCollection<Title>
. When you invoke OrderBy
on an ObservableCollection<T>
, the method returns an IOrderedEnumerable<T>
. We assign that object to the titleBindingSource
’s DataSource
property. When the DataSource
property changes, the DataGridView
iterates through the contents of the IEnumerable<T>
and displays the data.
Lines 46–49 filter the titles displayed by using the Where
extension method with the lambda expression
book => book.Copyright == “2016”
as an argument. The Where
extension method expects as its parameter a Func
delegate representing a method that receives one parameter and returns a bool
indicating whether the method’s argument matches the specified criteria. The lambda expression used here takes one Title
object (named book
) as its parameter and uses it to check whether the given Title
’s Copyright
property (a string
in the database) is equal to 2014
. A lambda expression that’s used with the Where
extension method must return a bool
value. Only Title
objects for which this lambda expression returns true
will be selected. We use OrderBy
to order the results by the Title1
property so the books are displayed in ascending order by title. The type of the lambda’s book
parameter is inferred from dbcontext.Titles.Local
, which contains Title
objects. As soon as the titleBindingSource
’s DataSource
property changes, the DataGridView
is updated with the query results.
Lines 54–58 filter the titles displayed by using the Where
extension method with the lambda expression
book => book.Title1.EndsWith(“How to Program”)
as an argument. This lambda expression takes one Title
object (named book
) as its parameter and uses it to check whether the given Title
’s Title1
property value ends with “How to Program”
. The expression books.Title1
returns the string
stored in that property, then we use the string class’s EndsWith
method to perform the test. We order the results by the Title1
property so the books are displayed in ascending order by title.