GridView 模板列包含自定義控件(內含 DropDownList + 3 Label),導出時默認渲染為 DropDownList 第一項,而非顯示用的 Label 值。
private static void PrepareControlForExport(Control control) {
for (int i = 0; i < control.Controls.Count; i++) {
Control current = control.Controls[i];
// 內置控件處理
if (current is LinkButton) ReplaceWithLiteral(current, ((LinkButton)current).Text);
else if (current is ImageButton) ReplaceWithLiteral(current, ((ImageButton)current).AlternateText);
else if (current is HyperLink) ReplaceWithLiteral(current, ((HyperLink)current).Text);
else if (current is DropDownList) ReplaceWithLiteral(current, ((DropDownList)current).SelectedItem.Text);
else if (current is CheckBox) ReplaceWithLiteral(current, ((CheckBox)current).Checked ? "True" : "False");
// 遞歸處理子控件
if (current.HasControls()) PrepareControlForExport(current);
}
}
static void ReplaceWithLiteral(Control original, string text) {
var parent = original.Parent;
int index = parent.Controls.IndexOf(original);
parent.Controls.RemoveAt(index);
parent.Controls.AddAt(index, new LiteralControl(text));
}
public interface IExportable {
string GetExportText();
}
public class MyCustomControl : CompositeControl, IExportable {
private Label _displayLabel;
// ...
public string GetExportText() => _displayLabel.Text;
}
// PrepareControlForExport 中擴展
if (current is IExportable exportable) {
ReplaceWithLiteral(current, exportable.GetExportText());
}
else if (current.GetType().Name == "MyCustomControl") {
var prop = current.GetType().GetProperty("DisplayText")
?? current.GetType().GetProperty("Text");
if (prop != null) {
ReplaceWithLiteral(current, prop.GetValue(current)?.ToString() ?? "");
}
}
// .browser 文件
// 適配器
public class MyCustomControlExportAdapter : ControlAdapter {
protected override void Render(HtmlTextWriter writer) {
var ctrl = (MyCustomControl)Control;
writer.Write(ctrl.DisplayLabel.Text); // 導出時只輸出文本
}
}
IExportable,編譯期檢查,零反射開銷GridViewExportUtil,避免分散在各控件ControlAdapter,徹底分離渲染與導出邏輯