Please, HELP!
I have put together a prototype solution that solves a scenario that requires me to manage a one to many relationship using a checklist of items. I am almost there, but I am having some problems trying to finish this off.
First, here is the solution I come with so far…
The template project contains a screen where a default grid is used for adding child entities. As well, an additional element on the screen displays a custom checklist control.
The overall solution is a health and safety management application that is used to keep track of, and report on, organizational health and safety information. A screen has been created to display the details of an injury incident. These details include master-detail type information such as; the parts of the body injured, the causes of the incident, causes of the injuries, and the natures of the injury.
These master-detail type relationships can be easily managed via the out-of-the-box grids that can be applied to the screen. For example, the following screenshot shows where one or more causes of incident can be added to the incident….
Simple grid of related causes of incident values.
What I have been able to do is implement a checklist enabled custom control that I created using the Telerik Silverlight GridView control…
The grid itself is bound to a screen data item of BodyPart entities…
Binding the custom control to the BodyPart entities was the easy part. Here is the XAML used for the control itself…
<UserControl x:Class="LightSwitchApplication.UserControls.BodyPartSelectionList"
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"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="294"
xmlns:telerik="http://schemas.telerik.com/2008/xaml/presentation">
<Grid x:Name="LayoutRoot" Background="White">
<telerik:RadGridView Name="gvBodyParts" Margin="0,0,0,0"
ItemsSource="{Binding Screen.BodyParts}"
AutoGenerateColumns="False" SelectionMode="Multiple"
ShowGroupPanel="False" ShowColumnHeaders="False"
ShowInsertRow="False" RowIndicatorVisibility="Collapsed"
IsReadOnly="True" SelectionChanged="gvBodyParts_SelectionChanged"
CanUserDeleteRows="False" CanUserInsertRows="False"
ActionOnLostFocus="None" EditTriggers="None"
IsReadOnlyBinding="{Binding}" Height="300" IsScrolling="False">
<telerik:RadGridView.Columns>
<telerik:GridViewSelectColumn />
<telerik:GridViewDataColumn
DataMemberBinding="{Binding Id}" Width="20" />
<telerik:GridViewDataColumn
DataMemberBinding="{Binding BodyPartName}"
Width="200" Header="Body Part" />
</telerik:RadGridView.Columns>
</telerik:RadGridView>
</Grid>
</UserControl>
Then, in the code behind of the control, I added an event handler that I could later consume on the LightSwitch screen. For example…
namespace LightSwitchApplication.UserControls
{
public partial class BodyPartSelectionList : UserControl
{
public event EventHandler SelectedBodyPartChanged;
protected virtual void OnSelectedBodyPartChanged(EventArgs e)
{
if (SelectedBodyPartChanged != null)
SelectedBodyPartChanged(this, EventArgs.Empty);
}
private void gvBodyParts_SelectionChanged(object sender, Telerik.Windows.Controls.SelectionChangeEventArgs e)
{
if (!_initialLoad)
{
if (e.AddedItems != null && e.AddedItems.Count > 0)
{
BodyPart bodyPart = e.AddedItems[0] as BodyPart;
if (bodyPart != null)
{
_selectedBodyPartId = bodyPart.Id;
_isSelected = true;
}
}
else
{
BodyPart bodyPart = e.RemovedItems[0] as BodyPart;
if (bodyPart != null)
{
_selectedBodyPartId = bodyPart.Id;
_isSelected = false;
}
}
OnSelectedBodyPartChanged(e);
}
}
}
}
Back in the screen itself, I added some goodness to capture the event that gets fired in the custom control…
namespace LightSwitchApplication
{
public partial class InjuryIncident
{
partial void InjuryIncident_Created()
{
_bodyPartsSelectionProxy = this.FindControl("BodyPartsSelectionGrid");
_bodyPartsSelectionProxy.ControlAvailable += OnBodyPartsSelectionGrid_ControlAvailable;
_bodyPartsSelectionProxy.ControlUnavailable += OnBodyPartsSelectionGrid_ControlUnavailable;
}
void OnBodyPartsSelectionGrid_ControlAvailable(object sender, ControlAvailableEventArgs e)
{
BodyPartSelectionList bodyPartSelectionList = e.Control as BodyPartSelectionList;
bodyPartSelectionList.SelectedBodyPartChanged += BodyPartsSelectionGrid_SelectionChanged;
bodyPartSelectionList.InjuryBodyPartsAssigned = InjuryBodyParts.ToArray();
}
void OnBodyPartsSelectionGrid_ControlUnavailable(object sender, ControlUnavailableEventArgs e)
{
BodyPartSelectionList bodyPartSelectionList = e.Control as BodyPartSelectionList;
bodyPartSelectionList.SelectedBodyPartChanged += BodyPartsSelectionGrid_SelectionChanged;
}
void BodyPartsSelectionGrid_SelectionChanged(object sender, EventArgs e)
{
BodyPartSelectionList bodyPartSelectionList = sender as BodyPartSelectionList;
int bodyPartId = bodyPartSelectionList.SelectedBodyPartId;
bool isSelected = bodyPartSelectionList.IsSelected;
if (_bodyPartSelectionOperation)
{
_bodyPartSelectionOperation = false;
UpdateIncidentBodyParts(bodyPartId, isSelected);
_bodyPartSelectionOperation = true;
}
}
private void UpdateIncidentBodyParts(int BodyPartId, bool IsSelected)
{
this.Details.Dispatcher.BeginInvoke(() =>
{
InjuryBodyPart injuryBodyPart;
if (IsSelected)
{
BodyPart bodyPart = (from bp in BodyParts where bp.Id == BodyPartId select bp).First();
// injuryBodyPart = DataWorkspace.ApplicationData.InjuryBodyParts.AddNew();
injuryBodyPart = this.InjuryBodyParts.AddNew();
injuryBodyPart.Incident = this.IncidentProperty;
injuryBodyPart.BodyPart = bodyPart;
}
else
{
injuryBodyPart = (from ibp in InjuryBodyParts
where (ibp.BodyPart.Id == BodyPartId)
&& (ibp.Incident.Id == this.IncidentProperty.Id)
select ibp).FirstOrDefault();
InjuryBodyParts.SelectedItem = injuryBodyPart;
InjuryBodyParts.SelectedItem.Delete();
//InjuryBodyParts.SelectedItem.Delete();
}
});
}
}
}
Now I am at a point where I need to bind the body parts that are assigned to the incident, and have those show as checked in the grid.
Any ideas?
I tried creating a property on the custom control that accepted a collection of body part entities, and then checked each of the body parts found in the grid, but I ran into some problems. For example:
public InjuryBodyPart[] InjuryBodyPartsAssigned
{
set
{
_initialLoad = true;
gvBodyParts.SelectedItems.Clear();
foreach (InjuryBodyPart injuryBodyPart in value)
{
gvBodyParts.SelectedItems.Add(injuryBodyPart.BodyPart);
}
_initialLoad = false;
}
}
Is there a better approach to this? I would prefer to do this via the checklist control I implemented, and not have to go back to the default grid.
Any ideas would be appreciated. (I’ll update the blog with any solution/resolution that I find).























No comments yet. Be the first!