Build Your Own Navigation Bar in WPF with Insert / Save / Delete Action

Some time ago, we built a navigation bar for our WPF application to navigate data. We can make it even more powerful, and add CRUD support into it. Because we are using Entity Data Framework, it’s pretty easy to achieve this. Don’t believe it? Let’s first add the following buttons into our navigation bar we built late time:

        <StackPanel Height=”28″ HorizontalAlignment=”Left” Margin=”103,232,0,0″ Name=”stackPanel2″ VerticalAlignment=”Top” Width=”119″ Orientation=”Horizontal”>

            <Button Background=”BlanchedAlmond” Content=”Insert” FontWeight=”Bold” Height=”23″ Name=”insertButton” Width=”Auto” Click=”insertButton_Click” /> 

            <Button Background=”BlanchedAlmond” Content=”Save” FontWeight=”Bold” Height=”23″ Name=”saveButton” Width=”Auto” Click=”saveButton_Click”/>

            <Button Background=”BlanchedAlmond” Content=”Delete” FontWeight=”Bold” Height=”23″ Name=”deleteButton” Width=”Auto” Click=”deleteButton_Click” />


It’s something like below:


Now let’s add the following event handler methods for each button:

1.       Insert button. Insert button adds a new empty entry for users to fill in data.

What we do here is pretty simple. We leverage the method IEditableCollectionViewSource.AddNew() to create a new entry into the current CollectionView. More info can be found here. Because the EmployeeID is assigned in the table automatically when a new row is inserted, we don’t need users to fill in this item.  


The code looks like below:


        private void insertButton_Click(object sender, RoutedEventArgs e)



            employeeIDTextBox.Text = “{Auto-assigned}”;



    Private Sub insertButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)

        CType(EmployeesViewSource__NorthwindEntities.View, BindingListCollectionView).AddNew()

        employeeIDTextBox.Text = “{Auto-assigned}”

    End Sub

2.       Save button. Save button saves the current data into database.

Let’s use ObjectContext.SaveChanges() to persist all updates to the database. SaveChanges method has an overload version SaveChanges(Boolean). If Boolean is set to false, then you have to call AccetpAllChanges() after calling SaveChanges(Boolean). For more information about this method, please check here 


Here we also need to consider about concurrency errors. For more information about how to handle this, please see here 


The code looks like below:



        private void saveButton_Click(object sender, RoutedEventArgs e)





                // Update the number of rows in the table in case it’s updated by data insertion.               



            catch (DBConcurrencyException ex)


                // Add business logic code to resolve the concurrency violation…




    Private Sub saveButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)



            ‘ Update the number of rows in the table in case it’s updated by data insertion.


        Catch ex As System.Data.DBConcurrencyException

            ‘ Add business logic code to resolve the concurrency violation…

        End Try

    End Sub

3.       Delete button. Delete button tends to delete the current entry.  

Here we instantiate an Employee object with the current item in the form and then use DeleteObject(TEntity) to do the deletion. However, the job isn’t submitted until users click Save button.



        private void deleteButton_Click(object sender, RoutedEventArgs e)


            Employee employee = employeesViewSource__NorthwindEntities.View.CurrentItem as Employee;

            if (employee != null)




            // Update the row count number and the current row number in the navigation bar.




    Private Sub deleteButton_Click(ByVal sender As Object, ByVal e As RoutedEventArgs)

        Dim employee As Employee = CType(EmployeesViewSource__NorthwindEntities.View.CurrentItem, Employee)

        If Not (employee Is Nothing) Then


        End If

        ‘ Update the row count number and the current row number in the navigation bar


    End Sub

Done! Now we can hit F5 and play with it. Have fun!

Comments (4)

  1. Nice post, thank you! Just a question: once you insert a new item, AddNew is invoked; what about CancelNew? I mean.. I need to implement a scenario like the one you described and I would like to understand how I can provide cancellation once the new item is added.

    Thank you very much!

  2. Yang Cao says:

    Would you like to add a "Discard" button? Maybe you could add an event handler so that once Discard button is clicked, the CancelNew method is called?


  3. XiaoyingGuo says:

    Hi Alessandro,

    May I understand better what kind of logic that you are going to implement? What do you mean by "once the new item is added"? Do you mean AddNew is invoked but before SaveChanges is invoked (so that the data isn’t really saved in database)? Or do you mean a new item is indeed added into the database?

    If it’s the previous one, implement your logic when you want to cancel the add transaction and then invoke the CancelNew like what Yang described above would cancel the add transaction and discard the pending new item.


  4. Hi, thanks for your kind replies. I mean AddNew is invoked but before SaveChanges, so the first solution should solve the problem.

    Thanks so much.