BpfLayout 0.4.0
See the version list below for details.
dotnet add package BpfLayout --version 0.4.0
NuGet\Install-Package BpfLayout -Version 0.4.0
<PackageReference Include="BpfLayout" Version="0.4.0" />
<PackageVersion Include="BpfLayout" Version="0.4.0" />
<PackageReference Include="BpfLayout" />
paket add BpfLayout --version 0.4.0
#r "nuget: BpfLayout, 0.4.0"
#:package BpfLayout@0.4.0
#addin nuget:?package=BpfLayout&version=0.4.0
#tool nuget:?package=BpfLayout&version=0.4.0
BpfLayout
A Blazor component library attempting to replicate WPF layout panels like Grid, StackPanel, and ScrollViewer in Blazor.
Why?
As a programmer moving familiar with how layout works in WPF, moving to Blazor with its HTML/CSS-based layout was incredibly frustrating. Elements were constantly resizing themselves when I didn't expect them to, things would scroll as I expected, etc. I wanted something that could give me the control I had with WPF in Blazor.
Goals
- Replicate as closely as possible the layout elements in WPF so that their use in Blazor would be intuitive.
- Work out-of-the-box with arbitrary child elements, especially in other component libraries like MudBlazor.
- Make it obvious why a layout is behaving the way that it is. Minimize the need to go hunting around in browser debugging tools.
Challenges
There are a couple of key challenges, beyond simply mapping WPF layout behavior to HTML/CSS, when trying to replicate WPF functionality in HTML/CSS:
- Blazor components are very weakly opinionated. They can contain effectively arbitrary HTML/CSS, and do not provide anything like the base functionality that
FrameworkElementprovides in WPF. As a result, getting a bunch of disparate components to play by similar layout rules is challenging. - Blazor has no notion of attached properties like WPF does. You cannot natively attach, for example,
Gridproperties to an arbitrary component or piece of HTML/CSS in Blazor.
Solutions
To solve the above problems, BpfLayout adopts the following convention:
Each layout panel has two parts: the panel itself, that provides the properties that the equivalent panel in WPF provides, and a wrapper "element" component used to host an arbitrary Blazor component or HTML/CSS. This wrapper component provides the parameters that FrameworkElement provides in WPF and attempts to impart them (using some internal CSS) to the hosted Blazor component or HTML/CSS.
Examples
For example, here is how a Grid works in BpfLayout:
<Grid RootWidthCss="800px" RootHeightCss="600px">
<GridRowDefinitions>
<GridRowDefinition Height="100" />
<GridRowDefinition Height="Auto" />
<GridRowDefinition Height="*" />
</GridRowDefinitions>
<GridColumnDefinitions>
<GridColumnDefinition Width ="200" />
<GridColumnDefinition Width ="*" />
<GridColumnDefinition Width ="2*" />
<GridColumnDefinition Width ="Auto" />
</GridColumnDefinitions>
</Grid>
<ChildContent>
<GridElement Row="0" Column="0" HorizontalAlignment="HorizontalAlignment.Stretch" VerticalAlignment="VerticalAlignment.Stretch">
<div class="some-class">
Hello, World!
</div>
</GridElement>
<GridElement Row="0" Column="1" Width="300">
<StackPanel Orientation="Orientation.Horizontal">
<StackPanelElement Width="150">
<div class="some-class3">
More Hello, World!
</div>
</StackPanelElement>
<StackPanelElement Height="10" VerticalAlignment="VerticalAlignment.Bottom">
<div class="some-class4">
More Hello, World!
</div>
</StackPanelElement>
</StackPanel>
</GridElement>
<GridElement Row="1" Column="2" Width="100" Height="50" HorizontalAlignment="HorizontalAlignment.Center">
<div class="some-class2">
Hello, World! Again!
</div>
</GridElement>
</ChildContent>
Here we a Grid with three rows and four columns, demonstrating the various sizing options for rows and columns. How does this differ from a WPF Grid?
- Note the presence of the
RootWidthCssandRootHeightCssproperties on theGridcomponent. This lets the user specify a CSS-based width and height for a panel component that is not nested inside other BpfLayout panels, then turns layout over to the BPF layout system. IfRootWidthCssorRootHeightCssare specified on a panel nested inside another panel, the panel's element width and height properties will override it.RootWidthCssandRootHeightCssdefault to100%so that in most contexts, the user will not even need to specify root sizes, the panel will simply consume all available space and turn subsequent layout over to the BpfLayout system. - The
Griditself does not have the standardFrameworkElementproperties for dimension or alignment. AllFrameworkElementproperties are present on the*Elementclasses, likeStackPanelElementorGridElement. Because theGridhere is a root, theRootWidthCssandRootHeightCssproperties effectively provide the initial size for this layout hierarchy. If we were to nest aGridinside aGridor aStackPanel, theFrameworkElementproperties for the nestedGridwould come from theGridElementorStackPanelElementthat hosts it. This keeps layout consistent between internal and external components in the BpfLayout system. - The row and column definitions aren't direct properties of the
Grid. In WPF, we would seeGrid.RowDefinitions, using XAML syntax to specify a direct value for theGridpropertyRowDefinitions. We don't have that option in Blazor, so instead, theRenderFragmentparametersGridRowDefinitionsandGridColumnDefinitionsare used to supply this information. - Child elements of the
Gridare not placed directly under theGriditself. Instead, they are placed under theChildContentRenderFragmentproperty. Again, this is simply how Blazor works. - Elements are not placed directly under
ChildContent. Instead, all child elements are wrapped in an element component. For aGrid, this isGridElement. These element components supply the equivalentFrameworkElementproperties from WPF and attempt to transform their child elements to honor these properties. Subsequent BpfLayout components can be nested inside these element components. In this example, thedivtags take all their sizing and alignment information from the element component in which they are nested. - The
RowandColumnproperites aren't attached properties as in WPF, but are rather properties of theGridElementclass.
| Product | Versions Compatible and additional computed target framework versions. |
|---|---|
| .NET | net6.0 is compatible. net6.0-android was computed. net6.0-ios was computed. net6.0-maccatalyst was computed. net6.0-macos was computed. net6.0-tvos was computed. net6.0-windows was computed. net7.0 was computed. net7.0-android was computed. net7.0-ios was computed. net7.0-maccatalyst was computed. net7.0-macos was computed. net7.0-tvos was computed. net7.0-windows was computed. net8.0 was computed. net8.0-android was computed. net8.0-browser was computed. net8.0-ios was computed. net8.0-maccatalyst was computed. net8.0-macos was computed. net8.0-tvos was computed. net8.0-windows was computed. net9.0 was computed. net9.0-android was computed. net9.0-browser was computed. net9.0-ios was computed. net9.0-maccatalyst was computed. net9.0-macos was computed. net9.0-tvos was computed. net9.0-windows was computed. net10.0 was computed. net10.0-android was computed. net10.0-browser was computed. net10.0-ios was computed. net10.0-maccatalyst was computed. net10.0-macos was computed. net10.0-tvos was computed. net10.0-windows was computed. |
-
net6.0
- Microsoft.AspNetCore.Components.Web (>= 6.0.10)
NuGet packages
This package is not used by any NuGet packages.
GitHub repositories
This package is not used by any popular GitHub repositories.