ContentIsland

ContentIslandè un'API WinUI 3 e SDK per app di Windows che consente di ospitare contenuto di rendering non XAML, ad esempio oggetti visivi di composizione, contenuti Win2D o superfici Direct3D, all'interno di un'app WinUI 3. Ogni isola è una superficie di rendering isolata con il proprio input, output, layout e stato di accessibilità. Si connette un'isola figlia a una posizione nell'isola padre usando un ChildSiteLink.

Usare ContentIsland per scenari di interoperabilità avanzati in cui è necessario contenuto non espresso come elementi XAML standard.

Note

ContentIsland è destinato a scenari di rendering avanzati. Per la maggior parte dell'interfaccia utente dell'app, usa controlli XAML WinUI 3 standard.

Funzionamento di ContentIsland

Un'app XAML WinUI 3 è già in esecuzione all'interno di un oggetto ContentIsland. È possibile ottenere l'isola principale da XamlRoot.ContentIsland. Per inserire contenuto non XAML aggiuntivo all'interno dell'albero XAML, puoi:

  1. Riservare spazio in XAML.
  2. Crea un elemento visivo di posizionamento nell'isola principale.
  3. Crea un oggetto ChildSiteLink per quell'elemento visivo di posizionamento.
  4. Creare un elemento figlio ContentIsland con il proprio oggetto visivo radice.
  5. Connetti l'isola figlia e mantieni dimensioni e trasformazione sincronizzate con il layout XAML.

L'isola figlia può quindi ospitare contenuti di composizione, grafica Win2D, elementi visivi basati su Direct3D o altri contenuti di rendering non XAML.

Riservare spazio in XAML

Inizia con un contenitore principale e un elemento segnaposto in cui apparirà l'isola figlia.

<Grid x:Name="RootPanel">
    <Border x:Name="IslandHost"
            Width="320"
            Height="200"
            HorizontalAlignment="Left"
            VerticalAlignment="Top" />
</Grid>

Crea un'isola figlia

Crea una visuale di posizionamento nell'isola principale, quindi crea e connetti l'isola figlia.

using System.Numerics;
using Microsoft.UI.Composition;
using Microsoft.UI.Content;
using Microsoft.UI.Xaml;
using Microsoft.UI.Xaml.Hosting;

private ChildSiteLink? _childSiteLink;
private ContentIsland? _childIsland;
private ContainerVisual? _placementVisual;
private ContainerVisual? _childRootVisual;

private void CreateContentIsland()
{
    ContentIsland parentIsland = IslandHost.XamlRoot.ContentIsland;
    Compositor compositor = ElementCompositionPreview.GetElementVisual(RootPanel).Compositor;

    // This visual marks where the child island appears inside the parent island.
    _placementVisual = compositor.CreateContainerVisual();
    ElementCompositionPreview.SetElementChildVisual(RootPanel, _placementVisual);

    _childSiteLink = ChildSiteLink.Create(parentIsland, _placementVisual);

    // Create the root visual for the child island's own scene graph.
    _childRootVisual = compositor.CreateContainerVisual();
    _childIsland = ContentIsland.Create(_childRootVisual);

    _childSiteLink.Connect(_childIsland);

    UpdateContentIslandLayout();
}

ContentIsland.Create usa Visual come radice per la scena dell'isola. Dopo che l'isola è connessa, è possibile aggiungere contenuto di composizione in tale oggetto visivo radice.

Posizionare l'isola rispetto a un elemento XAML

Mantieni sincronizzati l'indicatore visivo di posizionamento e il ChildSiteLink con il segnaposto. Questo esempio mappa i contorni del segnaposto nel pannello radice, quindi aggiorna sia l'elemento visivo di posizionamento sia il collegamento.

using System.Numerics;
using Windows.Foundation;

private void UpdateContentIslandLayout()
{
    if (_placementVisual is null || _childSiteLink is null)
    {
        return;
    }

    GeneralTransform transform = IslandHost.TransformToVisual(RootPanel);
    Point position = transform.TransformPoint(new Point(0, 0));

    Vector2 size = new((float)IslandHost.ActualWidth, (float)IslandHost.ActualHeight);
    Vector3 offset = new((float)position.X, (float)position.Y, 0);

    _placementVisual.Offset = offset;
    _placementVisual.Size = size;

    _childSiteLink.ActualSize = size;
    _childSiteLink.LocalToParentTransformMatrix =
        Matrix4x4.CreateTranslation(offset);
}

Sincronizzare le modifiche di layout

Sottoscrivi le modifiche al layout in modo che l'isola figlia rimanga allineata al segnaposto XAML.

public MainPage()
{
    this.InitializeComponent();

    // XamlRoot is null until the element is in the visual tree.
    // Defer ContentIsland creation to the Loaded event.
    IslandHost.Loaded += OnIslandHostLoaded;
    IslandHost.LayoutUpdated += OnIslandHostLayoutUpdated;
    IslandHost.Unloaded += OnIslandHostUnloaded;
}

private void OnIslandHostLoaded(object sender, RoutedEventArgs e)
{
    IslandHost.Loaded -= OnIslandHostLoaded;
    CreateContentIsland();
}

private void OnIslandHostLayoutUpdated(object sender, object e)
{
    UpdateContentIslandLayout();
}

Se si anima o si ridimensiona il segnaposto, chiamare UpdateContentIslandLayout ogni volta che cambia la dimensione effettiva o la posizione.

Aggiungi contenuto all'isola figlia

Dopo aver creato l'isola figlia, aggiungi il contenuto di composizione sotto l'elemento visivo radice figlio.

private void AddSpriteVisual()
{
    if (_childRootVisual is null)
    {
        return;
    }

    Compositor compositor = _childRootVisual.Compositor;

    SpriteVisual sprite = compositor.CreateSpriteVisual();
    sprite.Size = new Vector2(320, 200);
    sprite.Brush = compositor.CreateColorBrush(Microsoft.UI.Colors.DodgerBlue);

    _childRootVisual.Children.InsertAtTop(sprite);
}

Puoi sostituire SpriteVisual con il tuo albero visuale basato su Win2D o Direct3D.

Ripulisci le isole

ContentIsland e ChildSiteLink sono risorse bloccabili. Chiudi o eliminali quando non sono più necessari.

private void OnIslandHostUnloaded(object sender, RoutedEventArgs e)
{
    IslandHost.LayoutUpdated -= OnIslandHostLayoutUpdated;
    IslandHost.Unloaded -= OnIslandHostUnloaded;

    _childIsland?.Close();
    _childSiteLink?.Close();

    _childIsland = null;
    _childSiteLink = null;
    _placementVisual = null;
    _childRootVisual = null;
}

Gestisci la pulizia in Unloaded o durante la chiusura della finestra per rilasciare tempestivamente le risorse di rendering.

L'app Raccolta WinUI 3 include esempi interattivi di molti controlli e funzionalità della piattaforma WinUI 3.