Skip to content

Commit 908bc8e

Browse files
csharpfritzCopilot
andcommitted
docs: add NamingContainer documentation and cross-references
- Created docs/UtilityFeatures/NamingContainer.md with full component docs - Added NamingContainer to mkdocs.yml nav - Updated IDRendering.md with NamingContainer cross-references Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
1 parent f6acb56 commit 908bc8e

3 files changed

Lines changed: 200 additions & 0 deletions

File tree

docs/UtilityFeatures/IDRendering.md

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -150,6 +150,7 @@ All components inheriting from `BaseWebFormsComponent` support the ID parameter.
150150
- Child component IDs are prefixed with the parent's ID
151151
- Format: `ParentID_ChildID` (using underscore separator)
152152
- Follows the ASP.NET Web Forms `ClientIDMode.AutoID` pattern
153+
- For explicit naming scope control, see [NamingContainer](NamingContainer.md) and [WebFormsPage](WebFormsPage.md)
153154

154155
### Differences from Web Forms
155156

@@ -247,5 +248,7 @@ See the [ID Rendering Sample](/ControlSamples/IDRendering) for a complete workin
247248

248249
## Related Documentation
249250

251+
- [NamingContainer](NamingContainer.md) - Explicit naming scope component for ID hierarchy control
252+
- [WebFormsPage](WebFormsPage.md) - Combined naming container and theme wrapper
250253
- [ViewState](ViewState.md) - Understanding state management in migrated applications
251254
- [JavaScript Setup](JavaScriptSetup.md) - Configuring JavaScript for Blazor
Lines changed: 196 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,196 @@
1+
# NamingContainer
2+
3+
The `NamingContainer` component establishes a naming scope for child components, equivalent to [INamingContainer](https://learn.microsoft.com/dotnet/api/system.web.ui.inamingcontainer) in ASP.NET Web Forms. Child controls get IDs prefixed with this container's ID, separated by underscores — exactly as they did in Web Forms.
4+
5+
`NamingContainer` renders **no HTML of its own**. It is a purely structural component that exists solely to define the naming hierarchy for ID generation.
6+
7+
## Why It Exists
8+
9+
In Web Forms, any control implementing `INamingContainer` created a scope so that child controls received fully-qualified `ClientID` values. This ensured unique IDs across the page and enabled JavaScript and CSS selectors that relied on predictable ID patterns like `MainContent_txtUsername`.
10+
11+
Blazor has no built-in equivalent. `NamingContainer` fills that gap, letting your migrated JavaScript and CSS continue to target elements by their original Web Forms IDs.
12+
13+
## Features Supported in Blazor
14+
15+
- **Naming scope** — Prefixes child component IDs with the container's own ID using underscore separators
16+
- **UseCtl00Prefix** — Optionally prepends `ctl00` to the naming hierarchy for full Web Forms ID compatibility
17+
- **Nesting** — Multiple `NamingContainer` components can be nested; IDs accumulate through the hierarchy
18+
- **Visible** — Controls whether child content renders (inherited from `BaseWebFormsComponent`)
19+
20+
### Features NOT Supported
21+
22+
- **ClientIDMode** — Web Forms offered `AutoID`, `Static`, `Predictable`, and `Inherit` modes. This library uses a simplified model equivalent to `AutoID`.
23+
- **UniqueID** — The postback-oriented `UniqueID` (colon-separated) is not replicated; only `ClientID` (underscore-separated) is supported.
24+
25+
## Web Forms Syntax
26+
27+
```asp
28+
<%-- INamingContainer was typically an interface on custom controls or built-in containers --%>
29+
<asp:Panel ID="MainContent" runat="server">
30+
<asp:TextBox ID="txtSearch" runat="server" />
31+
<asp:Button ID="btnGo" runat="server" Text="Search" />
32+
</asp:Panel>
33+
```
34+
35+
Rendered IDs: `MainContent_txtSearch`, `MainContent_btnGo`
36+
37+
With `Page` as the root naming container and `ClientIDMode="AutoID"`:
38+
39+
```html
40+
<input id="ctl00_MainContent_txtSearch" type="text" />
41+
<input id="ctl00_MainContent_btnGo" type="submit" value="Search" />
42+
```
43+
44+
## Blazor Syntax
45+
46+
```razor
47+
<NamingContainer ID="MainContent">
48+
<TextBox ID="txtSearch" />
49+
<Button ID="btnGo" Text="Search" />
50+
</NamingContainer>
51+
```
52+
53+
With `UseCtl00Prefix`:
54+
55+
```razor
56+
<NamingContainer ID="MainContent" UseCtl00Prefix="true">
57+
<TextBox ID="txtSearch" />
58+
<Button ID="btnGo" Text="Search" />
59+
</NamingContainer>
60+
```
61+
62+
## Parameters
63+
64+
| Parameter | Type | Default | Description |
65+
|---|---|---|---|
66+
| `ID` | `string` | `null` | Sets the naming scope prefix for child component IDs |
67+
| `UseCtl00Prefix` | `bool` | `false` | When true, prepends `ctl00` to the naming hierarchy |
68+
| `Visible` | `bool` | `true` | Controls whether child content renders |
69+
| `ChildContent` | `RenderFragment` || The child components to wrap |
70+
71+
## Examples
72+
73+
### Basic Usage
74+
75+
Wrap a group of controls to establish a naming scope:
76+
77+
```razor
78+
<NamingContainer ID="SearchPanel">
79+
<Label ID="lblQuery" Text="Search:" />
80+
<TextBox ID="txtQuery" />
81+
<Button ID="btnSearch" Text="Go" />
82+
</NamingContainer>
83+
```
84+
85+
Rendered IDs:
86+
87+
| Component | Rendered `id` attribute |
88+
|---|---|
89+
| Label | `SearchPanel_lblQuery` |
90+
| TextBox | `SearchPanel_txtQuery` |
91+
| Button | `SearchPanel_btnSearch` |
92+
93+
Your existing JavaScript continues to work:
94+
95+
```javascript
96+
var query = document.getElementById('SearchPanel_txtQuery').value;
97+
```
98+
99+
### Nested Containers
100+
101+
`NamingContainer` components can be nested. Each level adds its ID as a prefix:
102+
103+
```razor
104+
<NamingContainer ID="Page">
105+
<NamingContainer ID="Sidebar">
106+
<TextBox ID="txtFilter" />
107+
</NamingContainer>
108+
<NamingContainer ID="Content">
109+
<Button ID="btnSave" Text="Save" />
110+
</NamingContainer>
111+
</NamingContainer>
112+
```
113+
114+
Rendered IDs:
115+
116+
| Component | Rendered `id` attribute |
117+
|---|---|
118+
| TextBox | `Page_Sidebar_txtFilter` |
119+
| Button | `Page_Content_btnSave` |
120+
121+
### UseCtl00Prefix for Full Web Forms Compatibility
122+
123+
In Web Forms, the page-level naming container prepended `ctl00` to all client IDs. Enable this behavior with `UseCtl00Prefix`:
124+
125+
```razor
126+
<NamingContainer ID="MainContent" UseCtl00Prefix="true">
127+
<TextBox ID="txtName" />
128+
<Button ID="btnSubmit" Text="Submit" />
129+
</NamingContainer>
130+
```
131+
132+
Rendered IDs:
133+
134+
| Component | Rendered `id` attribute |
135+
|---|---|
136+
| TextBox | `ctl00_MainContent_txtName` |
137+
| Button | `ctl00_MainContent_btnSubmit` |
138+
139+
This is essential when your JavaScript or CSS targets the full `ctl00_`-prefixed IDs that Web Forms generated.
140+
141+
### Migration Example
142+
143+
**Before (Web Forms):**
144+
```asp
145+
<form id="form1" runat="server">
146+
<asp:Panel ID="MainContent" runat="server">
147+
<asp:TextBox ID="txtEmail" runat="server" />
148+
<asp:Button ID="btnRegister" runat="server" Text="Register" />
149+
</asp:Panel>
150+
</form>
151+
152+
<script>
153+
// JavaScript targeting Web Forms IDs
154+
var email = document.getElementById('ctl00_MainContent_txtEmail');
155+
var btn = document.getElementById('ctl00_MainContent_btnRegister');
156+
</script>
157+
```
158+
159+
**After (Blazor):**
160+
```razor
161+
<NamingContainer ID="MainContent" UseCtl00Prefix="true">
162+
<TextBox ID="txtEmail" />
163+
<Button ID="btnRegister" Text="Register" />
164+
</NamingContainer>
165+
166+
<script>
167+
// JavaScript unchanged — same IDs as before
168+
var email = document.getElementById('ctl00_MainContent_txtEmail');
169+
var btn = document.getElementById('ctl00_MainContent_btnRegister');
170+
</script>
171+
```
172+
173+
## Relationship to WebFormsPage
174+
175+
[WebFormsPage](WebFormsPage.md) inherits from `NamingContainer` and adds theme/skin cascading. Use the table below to choose the right component:
176+
177+
| Component | Naming Scope | Theming | When to Use |
178+
|---|---|---|---|
179+
| `NamingContainer` ||| Nested naming scopes within a page, or when theming is not needed |
180+
| `WebFormsPage` ||| Layout-level wrapper providing both naming scope and theme support |
181+
182+
If you only need ID prefixing — for example, to scope a subsection of a page — use `NamingContainer`. If you need the full Web Forms `Page`-level experience (naming + themes), use `WebFormsPage` in your layout.
183+
184+
## Moving On
185+
186+
As you complete your migration away from Web Forms patterns:
187+
188+
1. **Replace string-based IDs with `@ref`** — Blazor's component references are type-safe and don't depend on naming conventions
189+
2. **Remove `ctl00` prefixes** — Update JavaScript to use simpler IDs, then set `UseCtl00Prefix="false"` or remove `NamingContainer` entirely
190+
3. **Use CSS classes instead of ID selectors** — CSS class selectors are more resilient and don't depend on component hierarchy
191+
192+
## See Also
193+
194+
- [ID Rendering](IDRendering.md) — How component IDs work across the library
195+
- [WebFormsPage](WebFormsPage.md) — Combined naming container and theme wrapper
196+
- [ViewState](ViewState.md) — How ViewState is emulated in Blazor

mkdocs.yml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,7 @@ nav:
123123
- Databinder: UtilityFeatures/Databinder.md
124124
- ID Rendering: UtilityFeatures/IDRendering.md
125125
- JavaScript Setup: UtilityFeatures/JavaScriptSetup.md
126+
- NamingContainer: UtilityFeatures/NamingContainer.md
126127
- PageService: UtilityFeatures/PageService.md
127128
- ViewState: UtilityFeatures/ViewState.md
128129
- WebFormsPage: UtilityFeatures/WebFormsPage.md

0 commit comments

Comments
 (0)