Lightswitch中没有树形展示的方式,也未找到第三方的扩展,只好用silverlight toolkit中的tree来实现。主要实现部门功能(自引用关系)
表定义如下
ID ,DeptName,ParentID
在LightSwitch中数据实体如下:
后来加了一个IsRoot 主要是用来获取根节点,Ls在查询条件时没办法设置参数值为null,只好将就一下来解决了。
建一个silverligth类库工程解决树的问题,主要二个文件,代码后续。
1.在需要树展示的屏幕中添加一个本地变量,类型Dept类型,同时编辑其过涉条件为IsRoot=true
2.在需要树展示的屏幕合适位置中添加一个自定义控件(就是我们建的工程,将数据源Screen赋上),命名为DeptTree(后面会用到)
3,在屏幕保存的地方,加上保存处理
partial void EditableDeptmentSetGrid_Saved()
{
// 在此编写您的代码。
DeptTree.Refresh();
}
<UserControl x:Class="SilverlightClassLibrary1.SilverlightTreeControl"
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:SilverlightClassLibrary1"
xmlns:sdk="http://schemas.microsoft.com/winfx/2006/xaml/presentation/sdk"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="400">
<UserControl.Resources>
<local:EntityCollectionValueConverter x:Key="EntityCollectionValueConverter" />
</UserControl.Resources>
<Grid x:Name="LayoutRoot" Background="White">
<StackPanel Orientation="Horizontal">
<sdk:TreeView Name="treeViewControl" ItemsSource="{Binding Screen.DeptTree}">
<sdk:TreeView.ItemContainerStyle>
<Style TargetType="sdk:TreeViewItem">
<Setter Property="IsExpanded" Value="True"/>
</Style>
</sdk:TreeView.ItemContainerStyle>
<sdk:TreeView.ItemTemplate>
<sdk:HierarchicalDataTemplate
ItemsSource="{Binding
Converter={StaticResource EntityCollectionValueConverter},
ConverterParameter=SubDepts}">
<StackPanel Orientation="Horizontal">
<TextBlock Text="{Binding Path=DeptName, Mode=TwoWay}"
Margin="5,0" Width="74" />
</StackPanel>
</sdk:HierarchicalDataTemplate>
</sdk:TreeView.ItemTemplate>
</sdk:TreeView>
</StackPanel>
</Grid>
</UserControl>
// By: Karol Zadora-Przylecki (Microsoft)
// From: http://bit.ly/oNTsJo
// Ensures that an entity collection is loaded before accessed by UI thread.
// The binding should use the whole entity object as data binding context
public class EntityCollectionValueConverter : IValueConverter
{
public object Convert(object value,
Type targetType,
object parameter,
System.Globalization.CultureInfo culture)
{
string strErrorMessage
= "Converter parameter should be set to the property name that will serve as source of data";
IEntityObject entity = value as IEntityObject;
if (entity == null)
throw new ArgumentException("The converter should be using an entity object");
string sourcePropertyName = parameter as string;
if (string.IsNullOrWhiteSpace(sourcePropertyName))
throw new ArgumentException(strErrorMessage);
// Enumerate the source property using logic dispatcher
// and prepare the collection of entities that the control will bind to
var entities = new ObservableCollection<IEntityObject>();
var temporaryEntites = new List<IEntityObject>();
entity.Details.Dispatcher.BeginInvoke(delegate
{
IEntityCollection eCollection =
entity.Details.Properties[sourcePropertyName].Value as IEntityCollection;
if (eCollection == null)
{
Debug.Assert(false, "The property " + sourcePropertyName + " is not an entity collection");
return;
}
// Now we are on the logic thread. We cannot just stuff the observable collection
// with entities because the collection will immediately raise Changed events
// and this will result in invalid cross-thread access. So we'll use a temporary collection
// and copy the entites again on the UI thread
foreach (IEntityObject e in eCollection)
{
temporaryEntites.Add(e);
}
Microsoft.LightSwitch.Threading.Dispatchers.Main.BeginInvoke(delegate
{
// I wish ObservableCollection had an AddRange() method...
foreach (IEntityObject e in temporaryEntites)
{
entities.Add(e);
}
});
});
return entities;
}
public object ConvertBack(object value,
Type targetType, object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}