在Dynamic Data Framework下实现Lookup字段下拉列表模板

背景

我们知道如果两个表之间有外键关系,Dynamic data framework会为相应的字段添加下拉列表来选择相应的值,提供了友好的操作方式。

但是在实际应用中我们通常会有些数据字典或者松散的关联关系,比如


这个图中,创建人就是来自用户表中。关系如下(两个关联的字段类型都是
Guid):


但二者并没有建立显式的外键关系。

我们希望在aspnet_module 在显示时,显示友好的名称,而不是一串Guid,在编辑的界面能够下拉选择。如下图:


解决方案

解决这个问题有两个方面:

  1. (1)        定制界面;
  2. (2)        获取数据,包括静态界面数据和下拉列表中的数据;

.net Framework3.5 SP1中,提供了强大的Metadata动态绑定方法,这是Dynamic data framework基础之一。网上已经有大量的资料来描述。值得一提的是UIHint这个属性,它为我们定制显示提供了很好的扩展能力。

[DisplayName("创建人")]

[UIHint("SamEnumeration", null, "TableName", "aspnet_Users","LookupField","UserId","ResultField","UserName")]

public Guid CreatedBy { get; set; }

我希望这个UIHint传入了参数

{TableName=” aspnet_Users”, LookupField ="UserId", ResultField="UserName"}

其含义就是 CreatedBy这个字段是来自于aspnet_UsersUserId字段,显示时请利用对应记录的UserName字段

我们需要定制两个ascx文件对对应的静态界面和编辑界面进行Render


对于静态的页面
SamEnumeration.ascx如何获取数据呢?

关键我利用了Linq中的ExecuteQuery方法,当然我们也可以利用Dynamic Expression表达式。关键就是拼一个sqlExecuteQuery去执行,代码如下:


ContractedBlock.gif ExpandedBlockStart.gif Code
 1  public static string GetLookupValue(string tableName, string lookupField, string resultField, string whereCondition, string FieldValueString)
 2         {
 3             string ret = string.Empty;
 4 
 5             //ret=(new MRPTablesDataContext()).aspnet_Users.Where(s => s.UserId.ToString() == FieldValueString).Select(s => s.UserName).First();
 6 
 7             if (!string.IsNullOrEmpty(FieldValueString))
 8             {
 9 
10                 string sql = string.Format("select {0} from {1} where {2}='{3}' and {4}", resultField, tableName, lookupField, FieldValueString,
11                     string.IsNullOrEmpty(whereCondition) ? "1=1" : whereCondition);
12 
13                 ret = new MRPTablesDataContext().ExecuteQuery<string>(sql).First();
14             }
15             return ret;
16         }

我增加了一个whereCondition来支持筛选一些记录。

这样我们就可以直接在SamEnumeration.ascxGetLookupValue的结果显示在页面上。前端代码很简单:

ContractedBlock.gif ExpandedBlockStart.gif Code
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SamEnumeration.ascx.cs" Inherits="SmallMRPV3.DynamicData.FieldTemplates.SamEnumeration" %>

<asp:Literal runat="server" ID="Literal1" Text="<%# getFieldValueString() %>" />

Code Behind:

ContractedBlock.gif ExpandedBlockStart.gif Code
public partial class SamEnumeration :FieldTemplateUserControl
    {
        
public override Control DataControl
        {
            
get
            {
                
return Literal1;
            }
        }
        
protected string getFieldValueString()
        {

            
string tableName = GetUIHintArg("TableName");
            
string lookupField = GetUIHintArg("LookupField");
            
string resultField = GetUIHintArg("ResultField");
            
string whereCondition = GetUIHintArg("WhereCondition");

            
string value = SamDBHelper.GetLookupValue(tableName, lookupField, resultField, whereCondition, FieldValueString);


            
return value;
        }
}

这里有一个技巧如何取得UIHint传过来的参数,请看代码:

ContractedBlock.gif ExpandedBlockStart.gif Code
protected string GetUIHintArg(string key)
        {

            UIHintAttribute hint 
= null;

            
string returnValue = string.Empty;

            hint 
= (UIHintAttribute)this.Column.Attributes[typeof(UIHintAttribute)];

            
if (hint != null)
            {

                
if (hint.ControlParameters.ContainsKey(key))
                {

                    returnValue 
= hint.ControlParameters[key].ToString();

                }

            }

            
return returnValue;

        }

同理我们定制SamEnumeration_Edit.ascx,这个比较复杂的地方在如何将数据绑定到dropdownlist中。前端代码依然很简单:

ContractedBlock.gif ExpandedBlockStart.gif Code
<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="SamEnumeration_Edit.ascx.cs" Inherits="SmallMRPV3.DynamicData.FieldTemplates.SamEnumeration_Edit" %>

<asp:DropDownList ID="DropDownList1" runat="server" CssClass="droplist">
</asp:DropDownList>

我定义了一个类来存放用于绑定的数据:

ContractedBlock.gif ExpandedBlockStart.gif Code
public class SamLookupData
    {
        
public string SAM_TextField { getset; }
        
public object SAM_ValueField { get;set;}
        
public SamLookupData() { }
        
public SamLookupData(string textFieldData, object valueFieldData)
        {
            SAM_TextField 
= textFieldData;
            SAM_ValueField 
= valueFieldData.ToString();
        }
    }

 

还是定义了一个取得数据的方法,和前面不同的是这个方法将返回一个IEnumerable<SamLookupData>类型。

ContractedBlock.gif ExpandedBlockStart.gif Code
 public static IEnumerable<SamLookupData> GetLookupEnum(string tableName, string lookupField, string resultField, string whereCondition)
        {
            IEnumerable
<SamLookupData> ret = null;



            
string sql = string.Format("select SAM_TextField={0},SAM_ValueField={2} from {1} where {3}", resultField, tableName, lookupField,
                
string.IsNullOrEmpty(whereCondition) ? "1=1" : whereCondition);

            ret 
= new MRPTablesDataContext().ExecuteQuery<SamLookupData>(sql);

            
return ret;
        }

看得出,我还是在拼这个SQL语句。

取得了这个之后,绑定到前端的dropdownlist就简单了。

在这个代码中我加入一个空值的item,便于将值设置为空。

ContractedBlock.gif ExpandedBlockStart.gif Code
protected void Page_Load(object sender, EventArgs e)
        {
            selectedValue 
= DropDownList1.SelectedValue;
            
string tableName = GetUIHintArg("TableName");
            
string lookupField = GetUIHintArg("LookupField");
            
string resultField = GetUIHintArg("ResultField");
            
string whereCondition = GetUIHintArg("WhereCondition");
            List
<SamLookupData> list=SamDBHelper.GetLookupEnum(tableName, lookupField, resultField, whereCondition).ToList();
            list.Insert(
0new SamLookupData() { SAM_TextField = "-", SAM_ValueField = null });
            DropDownList1.DataSource 
= list;
            DropDownList1.DataTextField 
= "SAM_TextField";
            DropDownList1.DataValueField 
= "SAM_ValueField";
            DropDownList1.DataBind();

        }

        
protected override void OnDataBinding(EventArgs e)
        {
            
base.OnDataBinding(e);
            
if (Mode == DataBoundControlMode.Edit && !string.IsNullOrEmpty(FieldValueString))
            {
                
try
                {
                    DropDownList1.SelectedValue 
= FieldValueString;
                }
                
catch
                {
                    DropDownList1.SelectedIndex 
= 0;
                }
            }
            
else if((Mode==DataBoundControlMode.Insert)||((Mode == DataBoundControlMode.Edit && string.IsNullOrEmpty(FieldValueString))))
            {
                DropDownList1.SelectedIndex 
= 0;
            }
        }

为了更改生效,需要重载方法

ExtractValues ,代码如下 :

ContractedBlock.gif ExpandedBlockStart.gif Code
 protected override void ExtractValues(IOrderedDictionary dictionary)
        {
            
object val = null;

            
if (!string.IsNullOrEmpty(selectedValue))
            {
                val 
= selectedValue;
            }
            dictionary[Column.Name] 
= val;
        }

到此这个问题已经得到了圆满解决。

 

转载于:https://www.cnblogs.com/PM_2004/archive/2009/10/11/1580853.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值