泛型和用户控件

本文关键字:控件 用户 泛型 | 更新日期: 2024-09-19 12:49:10

我是泛型的新手,所以我可能只是做得完全错误,但如下所示:我有一个小控件集合,我正在将这些控件组合成一个用户控件。看起来它会像预期的那样工作,但uc需要是通用的。在uc中,我有几个列表框(和一些按钮)。这些列表框和uc必须能够接受任何数量的通用列表。(即List<user>List<group>List<platform>等,然后返回对该通用列表的更改。我认为我可以接受该通用列表,但不确定如何返回通用列表。

控制:

<%@ Control Language="C#" AutoEventWireup="true" CodeBehind="AddRemoveList.ascx.cs" Inherits="NSDC_Supply.UserControls.AddRemoveList" %>
<table>
    <tr>
        <td><asp:ListBox ID="ListBox1" Width="150px" Height="100px" SelectionMode="Single" runat="server" /></td>
        <td><asp:Button ID="AddUser" runat="server" Text="<<" CausesValidation="false" onclick="AddUser_Click" /></td>
        <td><asp:Button ID="RemoveUser" runat="server" Text=">>" CausesValidation="false" onclick="RemoveUser_Click" /></td>
        <td><asp:ListBox ID="ListBox2" Width="150px" Height="100px" SelectionMode="Single" runat="server" /></td>
    </tr>
</table>

代码背后:

public partial class AddRemoveList : System.Web.UI.UserControl 
{
    public T EditedList { get; set; }  //Obviously this won't work
    protected void Page_Load(object sender, EventArgs e)
    {}
    public void FillListBox<T>(T collection1, T collection2, string val, string text)
    {
        ListBox1.DataSource = collection1;
        ListBox1.DataTextField = text;
        ListBox1.DataValueField = val;
        ListBox1.DataBind();
        ListBox2.DataSource = collection2;
        ListBox2.DataTextField = text;
        ListBox2.DataValueField = val;
        ListBox2.DataBind();
    }
    protected void AddItem_Click(object sender, EventArgs e)
    {
        if (ListBox2.SelectedIndex > -1)
        {
            ListBox1.Items.Add(ListBox2.SelectedItem);
            EditedList.Add(ListBox2.SelectedItem);
            ListBox2.Items.RemoveAt(ListBox2.SelectedIndex);
            ListBox1.ClearSelection();
        }
    }
    protected void RemoveItem_Click(object sender, EventArgs e)
    {
        if (ListBox1.SelectedIndex > -1)
        {
            ListBox2.Items.Add(ListBox1.SelectedItem);
            EditedList.Remove(ListBox2.SelectedItem);
            ListBox1.Items.RemoveAt(ListBox1.SelectedIndex);
            ListBox2.ClearSelection();
        }
    }
}

因此,首先我填充uc:

private void GridView1_SelectedIndexChanged(...)
{
    List<user> myUsers = selectedGroup.users.ToList();
    List<user> masterUserList = uc.GetAllUsers().OrderBy(g => g.full_name).ToList();
    UserControls.AddRemoveList ucarl = ((UserControls.AddRemoveList)FormView1.Controls[0].FindControl("ucAddRemoveList"));
    ucarl.FillListBox(myUsers, masterUserList, "id", "full_name");
}

然后在编辑uc中的列表框后,我尝试更新实体:

protected void FormView1_ItemUpdate(Object sender, FormViewUpdateEventArgs e)
{
    network_group editedGroup = new network_group();
    editedGroup.id = Convert.ToInt32(((Label)selectedControls.FindControl("lblid")).Text);
    editedGroup.full_name = ((TextBox)selectedControls.FindControl("txtfull_name")).Text;
    editedGroup.distribution_list_email = ((TextBox)selectedControls.FindControl("txtemail")).Text;
    UserControls.AddRemoveList ucarl = ((UserControls.AddRemoveList)FormView1.Controls[0].FindControl("ucAddRemoveList"));
    editedGroup.users.Add(ucarl);   //psudocode here
    ctx.SaveChanges();
}

如果我删除了对EditedList的所有调用,这是有效的,但我如何从uc中获得通用的EditedList?

更新:我得到的答案似乎是他们试图解决一个不同的问题……我想。下面是我尝试做的事情的更新:

我目前在一个页面上有两个列表框。我将从EntityFramework实体填充的对象列表绑定到ListBoxes。ListBox1是我当前正在查看的实体对象的实体对象子集合。ListBox2是子实体对象中所有可能的条目的集合。对于这个例子,我看到的是Group实体的一个实例。ListBox1是与该组关联的所有用户,ListBox2是公司中的所有用户。

列表框之间是添加/删除按钮,用于在两者之间来回移动项目。(因此,我可以使用AddItem_Click和RemoveItem_Clicck事件将用户添加到组或从组中删除用户,将设备添加到站点或从站点中删除设备等。然后,在FormView1_ItemUpdate事件中,我将在ListBox1(编辑的用户列表)中获取集合并将其保存到DB。)。

但因为我将做9次以上几乎完全相同的功能,所以我试图将这4个控件抽象成一个uc。通过这种方式,我可以传入任何两个List集合,即我想为任何给定对象绑定的文本和值字段,进行添加/删除,然后返回修改后的List。

因此,我的问题不是将项目从一个ListBox移到另一个,而是在完成后从ListBox1取回编辑过的List集合。这有帮助吗?它会改变任何答案吗?抱歉我说得太含糊了。

泛型和用户控件

我能想到的最简单的方法是添加一个扩展方法来实现这一点。如果所有对象都实现了一个具有属性idfullname的接口,例如:

public interface IListableObject
{
    string id { get; set; }
    string full_name { get; set; }
}

然后您可以为ListBox控件编写一个扩展方法:

public static List<T> GetListFromListBoxControl<T>(this ListBox source) where T: IListableObject, new()
{
    var returnValue = new List<T>();
    foreach(var item in source.Items)
    {
        returnValue.Add(new T() {
            id = item.Value,
            full_name = item.Text    
        });
    }
    return returnValue;
}

把它当作伪代码(我还没有测试过),但这个想法是合理的。然后你就可以直接从ListBox中获得你的列表:

var newList_of_users = ListBox.GetListFromListBoxControl<user>();

如果接口和扩展方法不是你的强项,那么你总是可以在某个地方写一个静态方法,并在一对一的基础上进行解析。

public static List<user> GetUsersFromListBox(ListBox source)
{
    var returnValue = new List<user>();
    foreach(var item in source.Items)
    {
        returnValue.Add(new user() {
            id = item.Value,
            full_name = item.Text    
        });
    }
    return returnValue;
}