Megosztás a következőn keresztül:


XAML-világítás a WinUI-ban

A CompositionLight objektumokat a SceneLightingEffecttel együtt használjuk a dinamikus világítás és a tükrözés szimulálásához.

Fényeket alkalmazhat a vizuális elemekre és az XAML UI-elemekre.

Fények alkalmazása XAML UI elemekre

XamlLight objektumokat arra használják, hogy CompositionLights segítségével dinamikus világítást adjanak a XAML UIElemekhez. A XamlLight metódusokat biztosít az UIElements vagy az XAML-kefe célzásához, fények alkalmazásához az UIElements-fákra, és segít kezelni a CompositionLight-erőforrások élettartamát attól függően, hogy éppen használatban vannak-e.

  • Ha egy XamlLight-tal ellátott ecsetet céloz meg, akkor az adott ecsetet használó UIElements részeit a fény világítja meg.
  • Ha XamlLight-tal céloz meg egy UIElement-et , akkor a teljes UIElement és annak gyermek UIElements elemeit a fény világítja meg.

XamlLight létrehozása és használata

A XamlLight egy alaposztály, amely egyéni fények létrehozásához használható.

Ez a példa egy egyéni XamlLight definícióját mutatja be, amely többszínű reflektorfényt alkalmaz a WinUI-ban a célzott felhasználói felületekre és ecsetekre.

public sealed class OrangeSpotLight : XamlLight
{
    // Register an attached property that lets you set a UIElement
    // or Brush as a target for this light type in markup.
    public static readonly DependencyProperty IsTargetProperty =
        DependencyProperty.RegisterAttached(
        "IsTarget",
        typeof(bool),
        typeof(OrangeSpotLight),
        new PropertyMetadata(null, OnIsTargetChanged)
    );

    public static void SetIsTarget(DependencyObject target, bool value)
    {
        target.SetValue(IsTargetProperty, value);
    }

    public static Boolean GetIsTarget(DependencyObject target)
    {
        return (bool)target.GetValue(IsTargetProperty);
    }

    // Handle attached property changed to automatically target and untarget UIElements and Brushes.
    private static void OnIsTargetChanged(DependencyObject obj, DependencyPropertyChangedEventArgs e)
    {
        var isAdding = (bool)e.NewValue;

        if (isAdding)
        {
            if (obj is UIElement)
            {
                XamlLight.AddTargetElement(GetIdStatic(), obj as UIElement);
            }
            else if (obj is Brush)
            {
                XamlLight.AddTargetBrush(GetIdStatic(), obj as Brush);
            }
        }
        else
        {
            if (obj is UIElement)
            {
                XamlLight.RemoveTargetElement(GetIdStatic(), obj as UIElement);
            }
            else if (obj is Brush)
            {
                XamlLight.RemoveTargetBrush(GetIdStatic(), obj as Brush);
            }
        }
    }

    protected override void OnConnected(UIElement newElement)
    {
        if (CompositionLight == null)
        {
            // OnConnected is called when the first target UIElement is shown on the screen.
            // This lets you delay creation of the composition object until it's actually needed.
            var spotLight = CompositionTarget.GetCompositorForCurrentThread().CreateSpotLight();
            spotLight.InnerConeColor = Colors.Orange;
            spotLight.OuterConeColor = Colors.Yellow;
            spotLight.InnerConeAngleInDegrees = 30;
            spotLight.OuterConeAngleInDegrees = 45;
            CompositionLight = spotLight;
        }
    }

    protected override void OnDisconnected(UIElement oldElement)
    {
        // OnDisconnected is called when there are no more target UIElements on the screen.
        // The CompositionLight should be disposed when no longer required.
        if (CompositionLight != null)
        {
            CompositionLight.Dispose();
            CompositionLight = null;
        }
    }

    protected override string GetId()
    {
        return GetIdStatic();
    }

    private static string GetIdStatic()
    {
        // This specifies the unique name of the light.
        // In most cases you should use the type's FullName.
        return typeof(OrangeSpotLight).FullName;
    }
}
// For the C++/WinRT code example below, you'll need to add a Midl File (.idl) file to your project.

// OrangeSpotLight.idl
namespace MyApp
{
    [default_interface]
    runtimeclass OrangeSpotLight : Microsoft.UI.Xaml.Media.XamlLight
    {
        OrangeSpotLight();
        static Microsoft.UI.Xaml.DependencyProperty IsTargetProperty{ get; };
        static Boolean GetIsTarget(Microsoft.UI.Xaml.DependencyObject target);
        static void SetIsTarget(Microsoft.UI.Xaml.DependencyObject target, Boolean value);
    }
}

// OrangeSpotLight.h
struct OrangeSpotLight : OrangeSpotLightT<OrangeSpotLight>
{
    OrangeSpotLight() = default;

    winrt::hstring GetId();

    static Microsoft::UI::Xaml::DependencyProperty IsTargetProperty() { return m_isTargetProperty; }

    static bool GetIsTarget(Microsoft::UI::Xaml::DependencyObject const& target)
    {
		return winrt::unbox_value<bool>(target.GetValue(m_isTargetProperty));
	}

    static void SetIsTarget(Microsoft::UI::Xaml::DependencyObject const& target, bool value)
    {
        target.SetValue(m_isTargetProperty, winrt::box_value(value));
    }

    void OnConnected(Microsoft::UI::Xaml::UIElement const& newElement);
    void OnDisconnected(Microsoft::UI::Xaml::UIElement const& oldElement);

    static void OnIsTargetChanged(Microsoft::UI::Xaml::DependencyObject const& d, Microsoft::UI::Xaml::DependencyPropertyChangedEventArgs const& e);

    inline static winrt::hstring GetIdStatic()
    {
        // This specifies the unique name of the light. In most cases you should use the type's full name.
        return winrt::xaml_typename<MyApp::OrangeSpotLight>().Name;
    }

private:
	static Microsoft::UI::Xaml::DependencyProperty m_isTargetProperty;
};

// OrangeSpotLight.cpp
Microsoft::UI::Xaml::DependencyProperty OrangeSpotLight::m_isTargetProperty =
    Microsoft::UI::Xaml::DependencyProperty::RegisterAttached(
        L"IsTarget",
        winrt::xaml_typename<bool>(),
        winrt::xaml_typename<MyApp::OrangeSpotLight>(),
        Microsoft::UI::Xaml::PropertyMetadata{ winrt::box_value(false), Microsoft::UI::Xaml::PropertyChangedCallback{ &OrangeSpotLight::OnIsTargetChanged } }
);

void OrangeSpotLight::OnConnected(Microsoft::UI::Xaml::UIElement const& /* newElement */)
{
    if (!CompositionLight())
    {
        // OnConnected is called when the first target UIElement is shown on the screen. This enables delaying composition object creation until it's actually necessary.
        auto spotLight{ Microsoft::UI::Xaml::Media::CompositionTarget::GetCompositorForCurrentThread().CreateSpotLight() };
        spotLight.InnerConeColor(Microsoft::UI::Colors::Orange());
        spotLight.OuterConeColor(Microsoft::UI::Colors::Yellow());
        spotLight.InnerConeAngleInDegrees(30);
        spotLight.OuterConeAngleInDegrees(45);
        CompositionLight(spotLight);
    }
}

void OrangeSpotLight::OnDisconnected(Microsoft::UI::Xaml::UIElement const& /* oldElement */)
{
    // OnDisconnected is called when there are no more target UIElements on the screen.
    // Dispose of composition resources when no longer in use.
    if (CompositionLight())
    {
        CompositionLight(nullptr);
    }
}

winrt::hstring OrangeSpotLight::GetId()
{
    return OrangeSpotLight::GetIdStatic();
}

void OrangeSpotLight::OnIsTargetChanged(Microsoft::UI::Xaml::DependencyObject const& d, Microsoft::UI::Xaml::DependencyPropertyChangedEventArgs const& e)
{
    auto uie{ d.try_as<Microsoft::UI::Xaml::UIElement>() };
    auto brush{ d.try_as<Microsoft::UI::Xaml::Media::Brush>() };

    auto isAdding = winrt::unbox_value<bool>(e.NewValue());
    if (isAdding)
    {

        if (uie)
        {
            Microsoft::UI::Xaml::Media::XamlLight::AddTargetElement(OrangeSpotLight::GetIdStatic(), uie);
        }
        else if (brush)
        {
            Microsoft::UI::Xaml::Media::XamlLight::AddTargetBrush(OrangeSpotLight::GetIdStatic(), brush);
        }
    }
    else
    {
        if (uie)
        {
            Microsoft::UI::Xaml::Media::XamlLight::RemoveTargetElement(OrangeSpotLight::GetIdStatic(), uie);
        }
        else if (brush)
        {
            Microsoft::UI::Xaml::Media::XamlLight::RemoveTargetBrush(OrangeSpotLight::GetIdStatic(), brush);
        }
    }
}

// MainPage.h
...
#include "OrangeSpotLight.h"
...
struct MainPage : MainPageT<MainPage>
{
    MainPage()
    {
        InitializeComponent();

		OrangeSpotLight::SetIsTarget(spotlitBrush(), true);
		OrangeSpotLight::SetIsTarget(spotlitUIElement(), true);
	}
...
};

Ezután bármilyen XAML felhasználói felületre vagy ecsetre alkalmazhatja ezt a fényt, hogy megvilágítsa őket. Ez a példa különböző lehetséges használatokat mutat be.

Fontos

C++/WinRT esetén távolítsa el az alábbi jelölés két előfordulásátlocal:OrangeSpotLight.IsTarget="True". A csatolt tulajdonságok már a háttérben lévő kódban vannak beállítva.

<StackPanel Width="100">
    <StackPanel.Lights>
        <local:OrangeSpotLight/>
    </StackPanel.Lights>

    <!-- This border is lit by the OrangeSpotLight, but its content is not. -->
    <Border BorderThickness="4" Margin="2">
        <Border.BorderBrush>
            <SolidColorBrush x:Name="spotlitBrush" Color="White" local:OrangeSpotLight.IsTarget="True"/>
        </Border.BorderBrush>
        <Rectangle Fill="LightGray" Height="20"/>
    </Border>

    <!-- This border and its content are lit by the OrangeSpotLight. -->
    <Border x:Name="spotlitUIElement" BorderThickness="4" BorderBrush="PaleGreen" Margin="2"
            local:OrangeSpotLight.IsTarget="True">
        <Rectangle Fill="LightGray" Height="20"/>
    </Border>

    <!-- This border and its content are not lit by the OrangeSpotLight. -->
    <Border BorderThickness="4" BorderBrush="PaleGreen" Margin="2">
        <Rectangle Fill="LightGray" Height="20"/>
    </Border>
</StackPanel>

Ennek az XAML-nek az eredményei így néznek ki.

Példák xaml fény által megvilágított elemekre

Fontos

Az UIElement.Lights beállítása a fenti példában látható módon csak olyan alkalmazások esetében támogatott, amelyek minimális verziója megegyezik a Windows 10 Alkotói Frissítésével vagy annál újabb verzióval. A korábbi verziókra célzó alkalmazások esetében a fényeket a háttérkódban kell létrehozni.

További források