Web表单模型绑定:如何省略不可见控件的绑定?

19
我正在使用.NET Framework版本4.5.1的WebForms的新模型绑定功能。我的目标是,基于某些条件排除部分双向绑定。 我非常喜欢(希望现在已经出名的)Scott Guthrie的博客系列。我使用Web Forms Model Binding Part 3: Updating and Validation (ASP.NET 4.5 Series)中的第二种方法实现了一个编辑页面。
这是我拥有的东西(在ElementEdit.aspx中简化):
<asp:FormView runat="server" ID="FormViewElement" RenderOuterTable="false" DefaultMode="Edit" DataKeyNames="ElementId"
    ItemType="Business.Entities.Element"
    SelectMethod="GetElement"
    UpdateMethod="UpdateElement">
    <EditItemTemplate>
        <asp:Panel runat="server" DefaultButton="ButtonSpeichern">
            <fieldset>
                /*some databound controls*/
                <asp:Panel runat="server" Visible="<%# !Item.CurrentElementData.SomeCondition() %>">
                    /*more databound controls*/
                </asp:Panel>
                /*the submit button ("ButtonSpeichern")*/
            </fieldset>
        </asp:Panel>
    </EditItemTemplate>
</asp:FormView>

如您所见,对于“更多数据绑定控件”中的包裹内部面板,存在一个可见性条件。当条件为真且它们可见时,应只进行绑定。否则,它们不应进行绑定或更改值。

更新的方式与Scott在帖子中(简化版,在xxPage.cs中)所述相同,这是Type Element的通用基类:

protected virtual bool UpdateEntity(int id) {
    T existing = UseCase.GetItem(id); //gets the original element    

    TryUpdateModel(existing); //SHOULD NOT update the invisible databound controls, but does

    ValidateExistingEntity(existing);    
    if (ModelState.IsValid) {
        UseCase.Update(existing);
        return true;
    }
    ShowErrors(ModelState);
    return false;
}

在调用TryUpdateModel()之后,不可见的控件已经更新了模型,这正是我想要避免的。

如何根据条件动态省略一些元素的数据绑定,即使设置它们不可见也没有帮助?

更新: 我现在有一个解决方法,可以解决今天我的问题:我只需创建两个具有各自代码背景的.aspx页面。根据用户应成功编辑哪些字段,我首先调用适当的页面。

然而,这并不能解决条件数据绑定的根本问题。

1个回答

7
这更像是一种算法而不是一个编码解决方案。
我喜欢使用一个单独的类来管理我的数据更新,例如MyData.cs,并通过这个类的方法传递UI元素。
我喜欢存储过程,但你可以在项目中创建查询。
如果控件之间的可见性存在差异,我建议:
MyBindingMethod(array[] of the controls){
    // Loop through array updating data.
    // Or loop through array and call a second method to update the data.
}

动态地检查控件的可见性,然后将它们添加到数组中或者不添加到绑定方法中。如果切换可见性的控件是恒定的,您可以使用两个单独的方法进行有选择的更新。
MyBindingMethodAll(){
    // Update all controls.

}

MyBindingMethodVisible(){
    // Update controls that remain visible.

}

然后在aspx.cs中调用MyData.cs中的方法。诀窍是在C#中控制数据绑定,您可以确定何时以及在哪里更新数据。

如果您能提供更多代码,我很乐意提供更详细的示例。


编辑更新以帮助澄清解决方案

通过使用单独的类来管理数据绑定,可以将显示元素传递给此单独类的方法。我已经使用了存储过程。

类ManageData

public static void SelectAllSomething(DropDownList list)
    {
        // Clear any previously bound items.
        list.Items.Clear(); 
        // SqlConnection.
        SqlConnection con = new SqlConnection(conString);
        // Create new command and parameterise.
        SqlCommand cmd = new SqlCommand();
        cmd.CommandType = CommandType.StoredProcedure;
        cmd.CommandText = "MyStoredProcedure";

        cmd.Connection = con;
        try
        {
            // Open connection and bind data to GUI.
            con.Open();

            list.DataSource = cmd.ExecuteReader();
            list.DataTextField = "Name";
            list.DataValueField = "ID";
            list.DataBind();

        }
        catch (Exception ex)
        {
            throw ex;
        }
        finally
        {
            con.Close();
            con.Dispose();
        }
    }

从你的aspx.cs调用ManageData类中的方法。
ManageData.SelectAllCat(MyDropDownList);

使用同样的原则。
没有看到你的布局,我只能给你一个概念性的例子。

  • 如果你想要控制文本框。

TextBox1、TextBox2、TextBox3、.../

public static void AddText(List<TextBox> MyTextBoxes)
{
    for(int i=0; i<MyTextBoxes.Count();i++){
        MyTextBoxes.[i].Text = // What means you are using.
    }

}

从aspx.cs文件中

public List<TextBox> FindVisibleTextBoxes(){

    List<TextBox> MyTextBoxes = new List<TextBox>();
    if(TextBox1.Visible== true){
        MyTextBoxes.Add(TextBox1);
    }

    return MyTextBoxes;

}

从ManageData将文本框列表传递到方法中。

根据您的需求,这可以更好地模块化,并且您可以传递多个列表或对象列表以通过异构控件混合

这只是一个概念,有许多方法可以解决问题。我希望您发现这对于开发更多解决方案有用。


2
谢谢。这似乎非常动态。不过它看起来相当复杂,削弱了新模型绑定的简单和美感。我希望能找到一些更简单的解决方案。但是,我现在已经实现了一个解决方法,请查看更新。 - Marcel
1
请不要管它。我最终会接受它的。你能提供一个关于绑定方法的链接,该方法接收一个控件数组以进行特定处理吗?我在谷歌上进行了快速搜索,但目前还没有找到更多信息。 - Marcel

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接