如何在运行时将ASP.Net控件移动到Web窗体上的不同位置?

时间:2021-01-17 15:53:18

Is there an accepted way to "move" a control.

是否有一种“移动”控件的可接受方式。

My client wants to place a certain chunk of markup (representing some visual element) in one of several different places on the page. The locations are different to the point that I can't effect the change on CSS along (by floating it or something).

我的客户想要在页面上的几个不同位置之一放置一定量的标记(代表一些视觉元素)。位置不同,我不能影响CSS的变化(通过浮动它或其他东西)。

I considered just putting the control in multiple spots with Visible set to "false," then displaying the one in the place they wanted for that particular page.

我考虑将控件置于多个位置,将Visible设置为“false”,然后在该特定页面所需的位置显示该控件。

However, the code for this control is not trivial -- there's a couple template sections, for instance. Having to dupe this in multiple places would get unwieldy. Also, I don't want to have to work with this control strictly from the code-behind for the same reason.

但是,这个控件的代码并不简单 - 例如,有几个模板部分。不得不在多个地方欺骗它会变得笨拙。此外,出于同样的原因,我不想严格地从代码隐藏中使用此控件。

So, I'd like to put it in one place on the Web form, the move it around based on where I want it. Could I put Placeholders in different spots, have the control in one spot, then remove and add it to the right spot? I suspect this would work.

所以,我想把它放在Web表单的一个地方,根据我想要的地方移动它。我可以将占位符放在不同的位置,将控件放在一个位置,然后将其删除并添加到正确的位置吗?我怀疑这会奏效。

Does someone have a better idea? Is there a best practice for this?

有人有更好的主意吗?这是最好的做法吗?

5 个解决方案

#1


I'd recommend using a placeholder control, moving your markup into a separate user control, then loading this at runtime and adding it to the relevant placeholder.

我建议使用占位符控件,将标记移动到单独的用户控件中,然后在运行时加载它并将其添加到相关的占位符。

Eg.

// Load a user control
MyControl userCtrl = (MyControl) LoadControl("~/Controls/MyControl.ascx");

// Or create an instance of your control
SubclassedControl subclassedCtrl = new SubclassedControl();

// Do stuff with controls here
userCtrl.LoadData();
subclassedCtrl.Text = "Hello World";

// Check which placeholder to add controls to
PlaceHolder placeHolder = (foo=="bar") ? placeHolder1 : placeHolder2;

// Add the controls
placeHolder.Controls.Add(userCtrl);
placeHolder.Controls.Add(subclassedCtrl);

This will avoid cluttering up your page with unnecessary markup, and loading it at runtime will also avoid unnecessary confusion later, when another developer looks at the code and can't immediately see why a control is in one place in the markup, but renders on a completely different part of the page.

这样可以避免使用不必要的标记使页面混乱,并且在运行时加载它也可以避免以后出现不必要的混淆,当另一个开发人员查看代码并且无法立即看到为什么控件在标记中的一个位置,但是渲染时页面的完全不同的部分。

#2


An alternative (and one I've seen done many times before) is through javascript and the DOM. Render your control inside a hidden div tag. So you would render your content here:

另一种选择(以及之前我见过很多次)是通过javascript和DOM。在隐藏的div标签内渲染您的控件。所以你会在这里呈现你的内容:

<div id='rendercontent' style='display:none'>
  .. control here ..
</div>

Then, lets say you wanted to move it all here (the span tag is inside because that's what we're going to replace):

然后,让我们说你想在这里全部移动(span标签在里面,因为那是我们要替换的):

<div id='newlocation1'><span></span></div>

You would define the following javascript:

您将定义以下javascript:

<script language="JavaScript">
function replaceNode(newElementID, targetElementID)
{
    var targetElement=document.getElementById(targetElementID);
    var newElement=document.getElementById(newElementID);
    targetElement.replaceChild(newElement, targetElement.firstChild);
}
</script>

And when you want to move the content to the new location, call:

当您想将内容移动到新位置时,请致电:

<script language="JavaScript">
replaceNode('rendercontent','newlocation1');
</script>

#3


Do Web Parts do what you want to do?

Web部件可以做你想做的事吗?

Or, you can change the parent programmatically of your controls to move them into a separate area.

或者,您可以以编程方式更改控件的父级,以将它们移动到单独的区域中。

#4


You can override the Render method and place the controls wherever you want in the html.

您可以覆盖Render方法并将控件放在html中的任何位置。

You only need to add controls to the Controls collection that must interact on the server. The rest of your HTML can just be written to the response stream. If you override Render you can create the html anyway you see fit, placing the controls in any order.

您只需要向必须在服务器上交互的Controls集合添加控件。您可以将其余HTML写入响应流。如果您覆盖渲染,您可以创建您认为合适的html,以任何顺序放置控件。

Below is an example of how to write out your html.

下面是如何写出你的html的一个例子。

protected override void Render(HtmlTextWriter writer)
{
  AddAttributesToRender(writer);
  writer.RenderBeginTag(TagKey);

  writer.RenderBeginTag(HtmlTextWriterTag.Div);
  _control.RenderControl(writer);
  writer.RenderEndTag();

  writer.RenderEndTag();
}

#5


You could always put panels in the pre-defined locations and add the control to the specific panel at runtime.. Here's an example adding a label (the label could be replaced with any control).

您始终可以将面板放在预定义的位置,并在运行时将控件添加到特定面板。这是添加标签的示例(标签可以替换为任何控件)。

Dim lblDisplay As Label = New Label()
lblDisplay.ID = "myLabel"
lblDisplay.Text = "Some Text"
pnlDisplay.Controls.Add(lblDisplay)

As far as...

据,直到...为止...

"Also, I don't want to have to work with this control strictly from the code-behind for the same reason."

“另外,出于同样的原因,我不想严格地从代码隐藏中使用这个控件。”

I think you're going to have to do most of your work in the code behind.

我认为你将不得不在后面的代码中完成大部分工作。

PS.. a good example of the whole usercontrol setup can be downloaded here.. http://www.asp.net/downloads/starter-kits/time-tracker/

PS ..整个用户控件设置的一个很好的例子可以在这里下载.. http://www.asp.net/downloads/starter-kits/time-tracker/

#1


I'd recommend using a placeholder control, moving your markup into a separate user control, then loading this at runtime and adding it to the relevant placeholder.

我建议使用占位符控件,将标记移动到单独的用户控件中,然后在运行时加载它并将其添加到相关的占位符。

Eg.

// Load a user control
MyControl userCtrl = (MyControl) LoadControl("~/Controls/MyControl.ascx");

// Or create an instance of your control
SubclassedControl subclassedCtrl = new SubclassedControl();

// Do stuff with controls here
userCtrl.LoadData();
subclassedCtrl.Text = "Hello World";

// Check which placeholder to add controls to
PlaceHolder placeHolder = (foo=="bar") ? placeHolder1 : placeHolder2;

// Add the controls
placeHolder.Controls.Add(userCtrl);
placeHolder.Controls.Add(subclassedCtrl);

This will avoid cluttering up your page with unnecessary markup, and loading it at runtime will also avoid unnecessary confusion later, when another developer looks at the code and can't immediately see why a control is in one place in the markup, but renders on a completely different part of the page.

这样可以避免使用不必要的标记使页面混乱,并且在运行时加载它也可以避免以后出现不必要的混淆,当另一个开发人员查看代码并且无法立即看到为什么控件在标记中的一个位置,但是渲染时页面的完全不同的部分。

#2


An alternative (and one I've seen done many times before) is through javascript and the DOM. Render your control inside a hidden div tag. So you would render your content here:

另一种选择(以及之前我见过很多次)是通过javascript和DOM。在隐藏的div标签内渲染您的控件。所以你会在这里呈现你的内容:

<div id='rendercontent' style='display:none'>
  .. control here ..
</div>

Then, lets say you wanted to move it all here (the span tag is inside because that's what we're going to replace):

然后,让我们说你想在这里全部移动(span标签在里面,因为那是我们要替换的):

<div id='newlocation1'><span></span></div>

You would define the following javascript:

您将定义以下javascript:

<script language="JavaScript">
function replaceNode(newElementID, targetElementID)
{
    var targetElement=document.getElementById(targetElementID);
    var newElement=document.getElementById(newElementID);
    targetElement.replaceChild(newElement, targetElement.firstChild);
}
</script>

And when you want to move the content to the new location, call:

当您想将内容移动到新位置时,请致电:

<script language="JavaScript">
replaceNode('rendercontent','newlocation1');
</script>

#3


Do Web Parts do what you want to do?

Web部件可以做你想做的事吗?

Or, you can change the parent programmatically of your controls to move them into a separate area.

或者,您可以以编程方式更改控件的父级,以将它们移动到单独的区域中。

#4


You can override the Render method and place the controls wherever you want in the html.

您可以覆盖Render方法并将控件放在html中的任何位置。

You only need to add controls to the Controls collection that must interact on the server. The rest of your HTML can just be written to the response stream. If you override Render you can create the html anyway you see fit, placing the controls in any order.

您只需要向必须在服务器上交互的Controls集合添加控件。您可以将其余HTML写入响应流。如果您覆盖渲染,您可以创建您认为合适的html,以任何顺序放置控件。

Below is an example of how to write out your html.

下面是如何写出你的html的一个例子。

protected override void Render(HtmlTextWriter writer)
{
  AddAttributesToRender(writer);
  writer.RenderBeginTag(TagKey);

  writer.RenderBeginTag(HtmlTextWriterTag.Div);
  _control.RenderControl(writer);
  writer.RenderEndTag();

  writer.RenderEndTag();
}

#5


You could always put panels in the pre-defined locations and add the control to the specific panel at runtime.. Here's an example adding a label (the label could be replaced with any control).

您始终可以将面板放在预定义的位置,并在运行时将控件添加到特定面板。这是添加标签的示例(标签可以替换为任何控件)。

Dim lblDisplay As Label = New Label()
lblDisplay.ID = "myLabel"
lblDisplay.Text = "Some Text"
pnlDisplay.Controls.Add(lblDisplay)

As far as...

据,直到...为止...

"Also, I don't want to have to work with this control strictly from the code-behind for the same reason."

“另外,出于同样的原因,我不想严格地从代码隐藏中使用这个控件。”

I think you're going to have to do most of your work in the code behind.

我认为你将不得不在后面的代码中完成大部分工作。

PS.. a good example of the whole usercontrol setup can be downloaded here.. http://www.asp.net/downloads/starter-kits/time-tracker/

PS ..整个用户控件设置的一个很好的例子可以在这里下载.. http://www.asp.net/downloads/starter-kits/time-tracker/