在 OpenExpressApp(OEA)中,「部門 + 崗位 = 角色」,功能權限歸屬角色,故配置在部門模組。傳統列表視圖需彈出對話框逐項勾選,操作繁瑣。新增 勾選視圖,將所有可選功能平鋪顯示,前置 CheckBox,單次點擊即可增刪權限,大幅提升易用性。
舊版:左側模組樹,右側分組功能清單。新增權限需點「選擇」→ 彈窗 → 勾選 → 確定 → 關窗。模組多時重複操作極其痛苦。

新版勾選視圖:右側直接列出所有功能,前置 CheckBox,勾選即新增、取消即移除,三步驟縮減為一步。

public static readonly DependencyProperty IsCheckedProperty =
DependencyProperty.RegisterAttached("IsChecked", typeof(bool), typeof(SelectedDataAttached),
new FrameworkPropertyMetadata(OnIsCheckedChanged));
private static void OnIsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) {
if (d is DataGrid grid) {
if ((bool)e.NewValue) {
var col = new DataGridCheckBoxColumn { Header = "選擇" };
col.Binding = new Binding(PropertyConvention.IsSelected);
grid.Columns.Insert(0, col);
} else if (grid.Columns[0] is DataGridCheckBoxColumn c && c.Header.Equals("選擇")) {
grid.Columns.RemoveAt(0);
}
}
}
public override void LoadData() {
base.LoadData();
if (AllowLoadData && AssociationOperateType.Selected == BOsPropInfo.AssociationAttribute.AssociationOperateType) {
var src = new LateBoundObject(_data).CallMethod(MethodConvention.GetList_Selected);
var dest = Parent.CurrentObject.GetPropertyValue(PropertyName);
Data = src;
(Control as UIElement).SetValue(SelectedDataAttached.DestDataProperty, dest);
}
}
public void FilterData(IQueryObject query) {
_data = Parent.CurrentObject.GetPropertyValue(PropertyName);
var obj = new LateBoundObject(_data);
if (AssociationOperateType.Self == ...) Data = obj.CallMethod(MethodConvention.GetList, query);
else {
Data = obj.CallMethod(MethodConvention.GetList_Selected, query);
var dest = obj.CallMethod(MethodConvention.GetList, query);
(Control as UIElement).SetValue(SelectedDataAttached.DestDataProperty, dest);
}
}
foreach (var item in srcData) {
((INotifyPropertyChanged)item).PropertyChanged += (s, e) => {
if (e.PropertyName == PropertyConvention.IsSelected) {
bool selected = (bool)s.GetPropertyValue(PropertyConvention.IsSelected);
if (view.BOsPropInfo.AssociationAttribute.IsForwardSelected) {
if (selected) AddObject(s, destData, view); else DeleteObject(s, destData, view);
} else {
if (selected) DeleteObject(s, destData, view); else AddObject(s, destData, view);
}
}
};
}
[Association(AssociationOperateType = AssociationOperateType.Selected,
IsForwardSelected = false,
SelectedPropertyMap = "BusinessObjectId;OperationId")]
public OrgPositionOperations OrgPositionOperations { ... }
AssociationOperateType.Selected:啟用勾選視圖IsForwardSelected:true=勾選→新增,false=勾選→刪除(反向)SelectedPropertyMap:來源屬性→目的屬性映射(新增時自動帶入)[BusinessObject("..."), Label("對象功能")]
public partial class BoInfoOperationSelected : GBusinessBase<BoInfoOperationSelected> {
private static PropertyInfo<bool> IsSelectedProperty = RegisterProperty(new PropertyInfo<bool>("IsSelected"));
[EntityProperty, ShowInList, Label("選擇"), ShowInLookup]
public bool IsSelected { get => GetProperty(IsSelectedProperty); set => SetProperty(IsSelectedProperty, value); }
// 其他屬性:BusinessObjectId, OperationId, ObjectName...
}
public BoInfoOperationSelectedList GetList_Selected(OrgPositionOperationCriteria criteria) {
return BoInfoOperationSelectedList.GetAggregationteList(criteria.BusinessObjectInfo);
}
完成上述三步,即可在零業務邏輯修改下,獲得高易用性的勾選式權限配置介面。