Migrating from Magnet 1.x to Magnet 2.0
Magnet 2.0 replaces the Cassowary solver with a compiled constraint engine and revises the public API. XAML written for 1.x does not compile against 2.0; this page maps every 1.x concept to its 2.0 counterpart.
Namespaces and types
| Magnet 1.x | Magnet 2.0 |
|---|---|
Nalu.MagnetLayout.* (MagnetStage, MagnetView, HorizontalBarrier, …) |
everything lives in Nalu (MagnetDefinition, MagnetView, MagnetBarrier, MagnetGuideline, MagnetChain) |
Magnet.Stage (IMagnetStage / MagnetStage) |
Magnet.Definition (MagnetDefinition) — created lazily when not assigned |
Magnet.StageId="x" attached property |
Magnet.MagnetId="x" |
Id on elements |
MagnetId (mandatory, unique; no auto-generated ids) |
"Stage" reserved id |
"parent" (MagnetAnchor.Parent) |
HorizontalPullTarget / VerticalPullTarget ("Stage.Left", "a.Right!") |
MagnetAnchor ("parent.Left", "a.Right,12,gone:0"); no ! traction |
Margin / CollapsedMargin (Thickness on the view element) |
per-anchor Margin and GoneMargin ("a.Right,12,gone:0") |
Width/Height (SizeValue: "1", "*", "50%", "1r", "1~") |
WidthSizing/HeightSizing (MagnetSizing: "48", "*", "50%", otherwise {nalu:MagnetSizing 1.5, Unit=Ratio} / Unit=StagePercent / Unit=Measured / Min/Max) |
SizeUnit.Stage ("50%" = 50% of the stage) |
{nalu:MagnetSizing 0.5, Unit=StagePercent}; note that "50%" now means 50% of the span between the view's two anchors |
SizeUnit.Measured coefficient ("1.5" = 1.5 × measured) |
{nalu:MagnetSizing 1.5, Unit=Measured}; a bare number is now a fixed size |
"*" with a single anchor (as wide as the stage) |
{nalu:MagnetSizing 1, Unit=StagePercent} |
SizeBehavior.Shrink (~) |
measured views are measured with their available span, so a wrapping view already fits; use max: for hard limits |
HorizontalBarrier / VerticalBarrier (Elements="a,b", Pole) |
MagnetBarrier (Direction, Nodes="a,b" or <x:String> content) |
HorizontalGuideline / VerticalGuideline (FractionalPosition, Position) |
MagnetGuideline (Orientation, Percent, Position) |
implicit chains (mutual anchors a.RightTo=b.Left + b.LeftTo=a.Right, Traction.Strong) |
explicit MagnetChain node (Style, Weights) |
Declaring constraints
1.x declared every view inside the stage and referenced it by StageId:
<nalu:Magnet>
<nalu:Magnet.Stage>
<nalu:MagnetStage>
<nalu:MagnetView Id="title" LeftTo="avatar.Right" TopTo="Stage.Top" Margin="12,0,0,0" />
</nalu:MagnetStage>
</nalu:Magnet.Stage>
<Label nalu:Magnet.StageId="title" />
</nalu:Magnet>
2.0 lets you write the constraints on the view (preferred), or keep a MagnetView in the definition bound by id:
<nalu:Magnet>
<Label nalu:Magnet.MagnetId="title" nalu:Magnet.LeftTo="avatar.Right,12" nalu:Magnet.TopTo="parent.Top" />
</nalu:Magnet>
Do not do both for the same id: it is an error (MagnetId 'title' is defined both in the MagnetDefinition and inline on a child view.).
Chains
Replace mutual anchors with a chain node. Margins between members go on the anchors to the adjacent member:
<nalu:Magnet.Definition>
<nalu:MagnetDefinition>
<nalu:MagnetChain MagnetId="row" Style="Packed">
<x:String>a</x:String><x:String>b</x:String>
</nalu:MagnetChain>
</nalu:MagnetDefinition>
</nalu:Magnet.Definition>
<Label nalu:Magnet.MagnetId="a" nalu:Magnet.LeftTo="parent.Left" nalu:Magnet.HorizontalBias="0" />
<Label nalu:Magnet.MagnetId="b" nalu:Magnet.LeftTo="a.Right,8" nalu:Magnet.RightTo="parent.Right" />
Visibility
1.x tracked Collapsed on the element; 2.0 reads IView.Visibility of the bound view (IsVisible="False"
collapses). A node can also declare ApplyVisibility="Hide"/"Show" (ConstraintSet-style scenes): a one-shot
action stamped onto the view's IsVisible when the definition is applied — see the Scenes section of the Magnet page.
Sharing definitions
1.x recommended sharing a MagnetStage from resources for CollectionView templates. 2.0 forbids sharing a
MagnetDefinition across layouts (it throws): declare it inline in the template — inflation (compile included) costs
a few tens of microseconds per instance.
Semantics that changed on purpose
- Measure hugs the content: every view (including views hanging outside via negative offsets) fits between the stage
edges;
*-sized children contribute their margins only. - A collapsed view drops its own margins (ConstraintLayout semantics).
- Barriers ignore collapsed members.
- Guideline
Positionis added to thePercent-based position. - A
Ratiowidth fed by a*/%height is resolved with a single cross-axis feedback iteration (1.x iterated the solver to convergence).