Sep
20
Written by:
Michael Washington
9/20/2010 8:01 PM
This is part III to the article LightSwitch Student Information System.
In this article we will explore taking LightSwitch to the edge of it’s abilities. We will do it for a good reason, and we will demonstrate that it is a tool that is capable of professional development.
This article continues from where the article, LightSwitch Student Information System (Part 2): Business Rules and Screen Permissions ended.
Note: You will need Visual Studio Professional, or higher, to complete this tutorial. You will not be able to create Silverlight Custom Controls if you only have the basic LightSwitch program installed.
In that article we implemented Attendance.
It is important to note that at the end of that article, the application does work. Also, while we added code to implement Business Rules, we did not have to write code for the application to work. It is an option to simply only enter valid data.
LightSwitch was designed for, and can be used effectively by non-programmers. However, if you are a programmer, or have access to one (all it takes is a little money), LightSwitch can be enhanced to be more productive than it already is.
At the end of the last article, the Attendance screen looks like the image above. While it does work, the problems are:
- You must enter the Attendance Code, Date, and Enrollment each time
- It is not easy to see the Attendance already entered
In “the real world”, a Teacher is usually sitting in front of a class (a Section) and staring at Students. In this situation, the Teacher knows what Section it is, and what day it is.
To be most effective, the Teacher wants to see a list of all the Students who are Enrolled in the class on that day (they do not want to see any Students who have dropped the class), and they want to quickly mark the Attendance for the Students.
We will have to implement a Silverlight Custom Control, because we need to perform functionality that does not normally exist in LightSwitch without some programming.
- We need to create in-memory records for Students that are enrolled but do not have an attendance record. LightSwitch is designed to require you to create each new record you want, as a new record, then save it. What people want, is for the computer to create “blank spots”, and allow them to fill in only the relevant data and click one button to “save all records”.
- We need to jump from the Section table to the Attendance table bypassing the Enrollment table. LightSwitch is designed to protect data integrity. When traversing from the Section table to the Attendance table, you need to select an Enrollment record first (a Section can have several Enrollments and an Attendance record is attached to an Enrollment record). We are going to bypass LightSwitch’s normal way of doing things (because we do not want the user to have to select each Enrollment before entering an Attendance record), while still maintaining it’s protections for our data integrity.
- We will only allow a Teacher to take Attendance for their own Students. This is also covered in this article: Filtering data based on current user in LightSwitch apps.
Create The Screen
Starting with the code from the previous article, we create a new Screen.
We create a New Data Screen called AttendanceForm, and we select (None) for Screen Data.
The Screen now looks like the image above.
Data Items
Click the Add Data Item… button, because we need to add two “parameters” that will be set by Screen elements and used to filter data in Query Filters, and in code.
The first one is UserName (String). This will be used to filter the data to only show a Teacher their Attendance.
The second one is AttendanceFormDate (Date). This will be used to filter Attendance to only show the selected date.
They will show up in the Designer.
Add Collections
We know that we will need to have a box for Teachers to select a Section and then take Attendance. Therefore, we need to add a Sections Collection and an Attendance Collection. Click the Add Data Item… button, and add a Sections Collection.
Add an Attendances Collection.
They will show up in the Designer.
Section Collection
Click the Edit Query link next to Sections.
Design the Query above (you can download the full source code at the end of the article).
Click Back to AttendanceForm to return to the Designer.
Click on Sections.
Set the Properties to the settings you see in the image above.
Click on the UserName Query Parameter under Sections.
In the properties, bind it to UserName Data Item.
Also, bind the AttendanceDate parameter to the AttendanceFormDate Data Item.
When you click on a parameter, you will see a line showing it’s associated Data Item.
Attendance Collection
Click the Edit Query link next to Attendances.
While this is a query for Attendance, we can drill into it’s associated tables and set the criteria for the Section Id.
Design the Query above (you can download the full source code at the end of the article).
Click Back to AttendanceForm to return to the Designer.
In the Designer, click on the SectionId Query Parameter under Attendances.
In the Properties, bind it to the Sections parameter.
You will be able to enter a “.” and navigate into the collection, and select SelectedItem.
Enter a “.” after SelectedItem, and select Id.
Bind it to Sections.SelectedItem.Id.
(This is how we are able to bypass the Enrollment collection and go from Sections to Attendance)
When you click on the parameter, you will see a line showing it’s associated Data Item.
Also, bind the AttendanceDate parameter to the AttendanceFormDate Data Item.
Set the Properties for the Attendances to the settings you see in the image above.
(Notice we turned off Auto Execute Query. We will create a Button that will run this query on demand. We do this because we would otherwise get inconsistent results when switching from a day that has Attendance records created in-memory, and a day that has actual saved Attendance records)
Design The Form In The Designer
In the Designer, change Rows Layout to Columns Layout.
Add a New Group.
Add the AttendanceFormDate.
Add the Sections.
Change the Sections to a List.
Right-click on the Command Bar, and Delete the Command Bar (you will still see it, but all the Buttons inside it will be removed).
Add Code
Add a new Button to the Screen Command Bar.
Name the Button, “Button”.
Right-click on the Button, and select Edit Execute Code.
Enter the following code:
partial void Button_Execute()
{
// Call the method that creates blank Attendance records when needed
UpdateAttendanceList();
// Load the Attendance collection
Attendances.Load();
}
Also add the following method:
private void UpdateAttendanceList()
{
int intSelectedSectionID = -1;
// Ensure we have a Section
if (Sections.SelectedItem != null)
{
intSelectedSectionID = Sections.SelectedItem.Id;
// Remove any unsaved Attendance
foreach (Attendance attendance in this.DataWorkspace.ApplicationData.Details.GetChanges()
.AddedEntities.OfType<Attendance>())
{
attendance.Details.DiscardChanges();
}
// Get all Enrollments for the day
var EnrollmentsMissingAttendance = from Enrollments in Sections.SelectedItem.Enrollments
where Enrollments.Attendances.
FirstOrDefault(x => x.AttendanceDate == AttendanceFormDate) == null
select Enrollments;
// We put this into a normal array to avoid the 'collection was modified' error
int[] intEnrollmentsWithoutAttendance = EnrollmentsMissingAttendance.Select(x => x.Id).ToArray();
int intTempID = -1;
// Loop through the Enrollments
foreach (int item in intEnrollmentsWithoutAttendance)
{
// Get the Enrollment record
Enrollment objEnrollment = DataWorkspace.ApplicationData.Enrollments_Single(item);
if ((objEnrollment.Attendances.FirstOrDefault(x => x.AttendanceDate == AttendanceFormDate) == null))
{
// Create an Attendance record for the Enrollment
Attendance a = objEnrollment.Attendances.AddNew();
//a.AttendanceCode = "P";
a.AttendanceDate = AttendanceFormDate;
// We need to give each record a unique ID so that the Silverlight contro can use this ID
// when it creates unique group names for the radio buttons
a.Id = intTempID;
intTempID--;
}
}
}
}
Also add the following method:
partial void AttendanceForm_Activated()
{
Microsoft.LightSwitch.Security.IUser currentUser = this.Application.User;
if (currentUser != null)
{
this.UserName = currentUser.Name;
}
}
In the Designer, in the properties for the Button, change it’s Display Name to Get Attendance.
The Custom Control
See: Creating A LightSwitch Custom Silverlight Control for directions on creating a Silverlight Custom Control project for LightSwitch.
Add a Silverlight 4 Class Library to the project, call it AttendanceForm.
Add two value converters to the project (AttendanceConverter.cs and AttendanceGroupConverter.cs). The code is below:
AttendanceConverter.cs:
using System;
using System.Windows.Data;
namespace AttendanceForm
{
public class AttendanceConverter : IValueConverter
{
#region Methods
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (value == null || parameter == null)
{
return value;
}
return value.ToString() == parameter.ToString();
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (value == null || parameter == null)
{
return value;
}
return (String)parameter;
}
#endregion Methods
}
}
AttendanceGroupConverter.cs:
using System;
using System.Windows.Data;
namespace AttendanceForm
{
public class AttendanceGroupConverter : IValueConverter
{
#region Methods
public object Convert(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
if (value == null || parameter == null)
{
return value;
}
return String.Format("{0}{1}", value.ToString(), parameter.ToString());
}
public object ConvertBack(object value, Type targetType, object parameter,
System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
#endregion Methods
}
}
Add a Silverlight User Control called Attendance.xaml.
Use this code for the XAML:
<UserControl
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:AttendanceForm" x:Class="AttendanceForm.Attendance"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="480" VerticalAlignment="Top" Width="Auto">
<UserControl.Resources>
<ResourceDictionary>
<local:AttendanceGroupConverter x:Key="AttendanceGroupConverter"/>
<local:AttendanceConverter x:Key="AttendanceConverter"/>
<DataTemplate x:Key="AttendanceTemplate">
<Grid HorizontalAlignment="Left" VerticalAlignment="Top">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="135.857"/>
<ColumnDefinition Width="0.25*"/>
<ColumnDefinition Width="0.25*"/>
<ColumnDefinition Width="0.25*"/>
<ColumnDefinition Width="0.25*"/>
</Grid.ColumnDefinitions>
<TextBlock TextWrapping="Wrap" Text="{Binding Enrollment.EnrollmentDisplay}" Width="370" HorizontalAlignment="Left"
VerticalAlignment="Center" TextTrimming="WordEllipsis"/>
<RadioButton GroupName="{Binding Id, ConverterParameter=P, Converter={StaticResource AttendanceGroupConverter}}"
IsChecked="{Binding AttendanceCode, ConverterParameter=P, Converter={StaticResource AttendanceConverter}, Mode=TwoWay}"
Grid.Column="1" HorizontalAlignment="Left" VerticalAlignment="Center" />
<RadioButton GroupName="{Binding Id, ConverterParameter=U, Converter={StaticResource AttendanceGroupConverter}}"
IsChecked="{Binding AttendanceCode, ConverterParameter=U, Converter={StaticResource AttendanceConverter}, Mode=TwoWay}"
VerticalAlignment="Center" Grid.Column="4" HorizontalAlignment="Left" d:LayoutOverrides="HorizontalAlignment" />
<RadioButton GroupName="{Binding Id, ConverterParameter=E, Converter={StaticResource AttendanceGroupConverter}}"
IsChecked="{Binding AttendanceCode, ConverterParameter=E, Converter={StaticResource AttendanceConverter}, Mode=TwoWay}"
VerticalAlignment="Center" Grid.Column="3" HorizontalAlignment="Left" />
<RadioButton GroupName="{Binding Id, ConverterParameter=T, Converter={StaticResource AttendanceGroupConverter}}"
IsChecked="{Binding AttendanceCode, ConverterParameter=T, Converter={StaticResource AttendanceConverter}, Mode=TwoWay}"
VerticalAlignment="Center" Grid.Column="2" HorizontalAlignment="Left" />
</Grid>
</DataTemplate>
</ResourceDictionary>
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<Grid.ColumnDefinitions>
<ColumnDefinition/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition/>
</Grid.RowDefinitions>
<ListBox x:Name="AttendancelistBox" ItemsSource="{Binding Screen.Attendances}"
ItemTemplate="{StaticResource AttendanceTemplate}" BorderThickness="2" d:LayoutOverrides="GridBox"
Margin="2,41,0,0" VerticalAlignment="Top" />
<Grid HorizontalAlignment="Left" VerticalAlignment="Top" Margin="8,16,0,0" Width="448">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="371.47"/>
<ColumnDefinition Width="0.299*"/>
<ColumnDefinition Width="0.238*"/>
<ColumnDefinition Width="0.269*"/>
<ColumnDefinition Width="0.194*"/>
</Grid.ColumnDefinitions>
<TextBlock TextWrapping="Wrap" Text="Student / Enrollment" VerticalAlignment="Top" Margin="0,0,19,0"/>
<TextBlock TextWrapping="Wrap" Text="P" Width="13" Grid.Column="1" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<TextBlock TextWrapping="Wrap" Text="T" Width="12" Grid.Column="2" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<TextBlock TextWrapping="Wrap" Text="E" Width="13" Grid.Column="3" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<TextBlock TextWrapping="Wrap" Text="U" Width="13" Grid.Column="4" HorizontalAlignment="Center" VerticalAlignment="Top"/>
</Grid>
</Grid>
</UserControl>
Build the Solution.
Consuming The Silverlight Custom Control
Return back to the LightSwitch Designer, right-click on Attendance Form, and select Add Group.
Under the new Group, click Add, and select New Custom Control.
Click the Add Reference Button.
Create a Project reference to the AttendanceForm project.
Select the Attendance control, and click OK.
Set the properties for the control according to the image above.
Run the project.
You need to enter a date for Attendance, then click the Get Attendance button for the Attendance to show. After entering the Attendance, you click the Save button to save the changes.
You can download the code here:
http://silverlight.adefwebserver.com/files/lightSwitch/LightSwitchStudentInformationSystem_part3.zip
The LightSwitch Student Information System Series
45 comment(s) so far...
You rock!!
Now for gods sake man, get some sleep ;)
Paul
By Paul Patterson on
9/20/2010 8:48 PM
|
@Paul Patterson - Thanks. I'm off to bed...
By Michael Washington on
9/20/2010 8:49 PM
|
Hi
Create write-up. Helped a lot.
I was wondering how one could connect to a Access DB? I know that build-in support might be planned for future releases, but that means more waiting ;)
I know a Access DB isn't the best thing in the world, but sometimes installing SQL server is just overkill for a dead simple client manager which will only be used by one user.
Anyway, it's more for interest than anything else. Any info would be greatly appreciated.
Regards Nick
By Nick on
10/31/2010 5:29 AM
|
@Nick I do not think it is possible to run on anything but SQL Server or SQL Express. SQL Express should be economical and easy to deploy.
By Michael Washington on
10/31/2010 5:31 AM
|
Great Article on LightSwitch We are using a similar database schema for a school system project. So, the example is quite 'live' to our situation. One(amongst many) things we're considering is transaction logging for accounting purpose. How does LightSwitch handle logs?
By ergodave on
11/2/2010 10:50 AM
|
@ergodave - It should be easy to programmatically write to a log table whenever records are updated. You would write the code just once in the Data layer and you're done. Should take about 5 minutes to write the code :)
By Michael Washington on
11/2/2010 10:51 AM
|
Thanks for the reply. Lightswitch is very useful. Writing the logging in a few minutes, franking that is a deep dive for many into the code. So, Logging as an lightswitch extension? That would something to see in demo.
By ergodaveh on
11/5/2010 4:11 AM
|
Thank you sir This is exactly what I want But if it allowed me to ask you How do I make inquiries about the Attendance of a group of students between the start date and end date? Please I need this answer Thank you once again
By anwar on
11/7/2010 1:46 PM
|
@anwar - you would use the custom query, however I would be unable to provide any examples due to my work load
By Michael Washington on
11/7/2010 6:46 PM
|
Thank you
By anwar on
11/12/2010 2:54 PM
|
I found that it is possible to use SQLite with lightswitch beta1 after you install the SQLite data provider. Works pretty great :)
Now I have published my app and installed on a XP machine which does not have VS LightSwitch installed. All went well and the app runs fine except for the Customize Screen Button which is still visible and working.
Did I do something wrong, or did I just miss something??
Regards
By Nick on
11/13/2010 6:26 AM
|
@Nick - Wow I did not know that was possible. In LightSwitch Beta 1 the Customize button is always visible.
By Michael Washington on
11/13/2010 6:27 AM
|
Aah, OK. I guess it will go away with later releases then.
Thanks
By Nick on
11/15/2010 5:51 AM
|
@Nick - You can turn off the Customize button by going to Build > Configuration Manager and changing from Debug to Release.
@Michael - Does this custom control actually send data back to the application/database ? That is something I am strugling with right now. I have created a custom control that is a CheckBoxList. The list is created by binding to screen data from the LightSwitch screen. I now need the LightSwitch app to be able to see which options are checked and act on the data.
By Shane on
12/21/2010 3:03 PM
|
@Shane - Just make sure you have 2 way binding. You can download and run the code and see that it updates :)
By Michael Washington on
12/21/2010 3:03 PM
|
Are these converters needed for the application/control interaction ? I have two way binding, I just don't know how to make my control tell the lightswitch app which entries are checked. My control is just the basic XAML below:
I have to check to see if a body part is checked so that I can create an entry in a cross reference table with the body_part_id. I know you are busy and don't have time to walk me through it, but anything to point me in the right direction would be greatly appreciated. Thanks again.
By Shane on
12/22/2010 9:42 AM
|
@Shane - This site has the only examples of what you are looking for that I know of.
By Michael Washington on
12/22/2010 10:10 AM
|
hi good job want to know if it would do to qualify as students notes by subject bone and an average final
By fedison72 on
3/3/2011 11:15 AM
|
@fedison72 - Since I provide the source code you could easily add that.
By Michael Washington on
3/3/2011 11:16 AM
|
Hi, Excellent article ! but could not find the source code
Thank you, Adrian
By ady2011 on
3/28/2011 11:47 AM
|
@ady2011 - I have to re-do te code for Beta 2 in the next week or so.
By Michael Washington on
3/28/2011 12:17 PM
|
Nice work Michael.
You've sure put a lot of effort into your example. This is great for the LS community,
Yann
By Yann on
4/5/2011 4:14 AM
|
Great post and very good step by step introduction. Thanks
By Juanlu, elGuerre on
5/17/2011 1:45 PM
|
@Juanlu, elGuerre - Thank You for leaving a comment.
By Michael Washington on
5/17/2011 1:45 PM
|
Thanks Micheal for all your efforts. You are a blessing to humanity.
By gabimb on
8/8/2011 10:49 AM
|
@gabimb - Thank You!
By Michael Washington on
8/8/2011 11:42 AM
|
Hi there, are you planning to post the Grades section as part 4 of this tutorial?
Great job!
Thanks!
By Daniel Gzz on
12/22/2011 9:09 PM
|
@Daniel Gzz - I am not sure. The main delay is that I need to make a LightSwitch application that can be enhanced using extensions rather than requiring people to start from scratch because they may have the version that does not have the Grades module but have customized their app.
By Michael Washington on
12/22/2011 9:12 PM
|
Thank you for this example. I need to do something sort of similar but I'm having a few issues understanding HOW this button group is assigning a value to a specific field. Here is what I am doing and maybe you can enlighten me which I would appreciate. I am building an app for a department that has a form that is somewhat like a survey. It would have 5 radio buttons with values 0 to 5 (the old Strongly Disagree to Strongly Agree type of outcome.) It has a series of questions and for the sake of the example say there are 10 questions. I have one table with 2 or 3 key fields and in the same table, I have fields Q1 thru Q10 to store the answers to the questions.
Now, this would normally be so easy it could be done in your sleep; however, since you have to build a custom control in Lightswitch, I missing something. I simply want this: A button group with 5 buttons that allows each button to, if checked, assign a value to a single field in a recordset. Does that make sense?
Any help is truly appreciated!!
By Chris Leo on
6/21/2012 12:00 PM
|
@Chris Leo - There is no simple way to explain this because it is a issue around how to make Silverlight do what you need. LightSwitch is not the issue. I have another Silverlight example that uses radio button here: http://www.codeproject.com/Articles/127409/Silverlight-Super-Tabs-Interface-using-View-Model
By Michael Washington on
6/21/2012 12:02 PM
|
Hi. I built this app from scratch per the steps in the tutorial successfully. Now I am trying to apply it to a personal project and the listbox doesn't display the students. The proper amount of radiobuttons appear, but the names and other data doesn't show. Also if I tick a radiobutton and attempt to save, validation errors occur asking for the 'AttendanceCode', which in my case is 'Type'. The names of the students appear in the lightswitch popup form that is created when the individual validation link is clicked. So I guess my question is two part: What do I need to troubleshoot to find why the names are not being displayed? What do I troubleshoot to see that the control is bound to the Attendance table?
By wdarnellg on
5/12/2013 8:03 AM
|
@wdarnellg - Please make a post in the official LightSwitch Forums (http://social.msdn.microsoft.com/Forums/en-US/lightswitch/threads) for assistance with your particular issue. The Blog comments are not a good place to resolve issues. Thanks
By Michael Washington on
5/12/2013 8:07 AM
|
Ok, Will do. Thanks.
By wdarnellg on
5/12/2013 9:16 AM
|
Hi,
thanks for the great tutorial it has really helped me better understand light switch and apply it to my own project. Just having a few teething issues that i would like to run past you if you have the time.
By Eneto on
9/4/2013 12:20 PM
|
@Eneto - Please make a post in the official LightSwitch Forums (http://social.msdn.microsoft.com/Forums/en-US/lightswitch/threads)
By Michael Washington on
9/4/2013 12:22 PM
|
Hi Michael,
I am working through Part 3 and I get to the place where you say:
"Also add the following method: private void UpdateAttendanceList()...."
and
" Also add the following method: partial void AttendanceForm_Activated()...."
I am not at all familiar with C#. I did manage to add the first of these two snippets added but fail to add the second method without getting a host of errors. Is there an easy way to identify exactly where the code should be inserted into the New Button on the AttendanceForm just prior to creating the Custom Control?
Thank you, for these tutorials and your help. Mark
By Mark on
8/12/2014 4:39 AM
|
@Mark - No, not that I know of.
By Michael Washington on
8/12/2014 4:43 AM
|
Hi Mike,
Thank you for your response. I finally was able to add the code correctly and it works great. The end users however are never quite pleased. They would like to know if there is a way to put in a "Select All" for the P, U, or E, columns in the Attendance control? The way their sections are set up is that they could have as many as 30 people enrolled but as few as 6 people might show up. Short of the "Select All" option is there a way to make it every student's attendance default to "P" when the "Get Attendance" button is pushed. Thank you for your work. Mark
By Mark on
9/4/2014 1:24 PM
|
@Mark - Yes it is possible but I have no examples, sorry.
By Michael Washington on
9/4/2014 1:25 PM
|
Hi Michael,
It seems clear to me that the "Attendance Form" would not work on ipads but would it work on Android and Windows tablets? Also, does this need to be published from Lightswitch as Desktop client app or can it published as an html app to be used on via a browser? Thank you, Mark
By Mark on
10/22/2014 7:52 AM
|
@Mark - This uses Silverlight and it will not work on IPads or Android. It will only work on Windows 8 Pro tablets. It is recommended that you use LightSwitch HTML Client not LightSwitch Desktop Client.
By Michael Washington on
10/22/2014 7:54 AM
|
did you have tutorial to do attendance form in html client?
By Mahoda on
7/14/2016 4:58 AM
|
@Mahoda - Sorry no.
By Michael Washington on
7/14/2016 4:58 AM
|
can you see me the part of code that show list of students?
By Mahoda on
7/14/2016 4:33 PM
|
@Mahoda - All the code is one the download page.
By Michael Washington on
7/14/2016 4:33 PM
|