XamlLight
XamlLight
XamlLight
XamlLight
Class
Definition
Provides a base class used to create XAML lights that use a CompositionLight to apply lighting effects to XAML elements and brushes.
public : class XamlLight : DependencyObject, IXamlLight, IXamlLightOverrides, IXamlLightProtectedpublic class XamlLight : DependencyObject, IXamlLight, IXamlLightOverrides, IXamlLightProtectedPublic Class XamlLight Inherits DependencyObject Implements IXamlLight, IXamlLightOverrides, IXamlLightProtected// This API is not available in Javascript.
- Inheritance
-
XamlLightXamlLightXamlLightXamlLight
- Attributes
| Device family |
Windows 10 Creators Update (introduced v10.0.15063.0)
|
| API contract |
Windows.Foundation.UniversalApiContract (introduced v4)
|
Inherited Members
Inherited methods
Inherited properties
Examples
This example shows the definition for a custom XamlLight that applies a multicolored spotlight to targeted UIElements and Brushes:
public sealed class OrangeSpotLight : XamlLight
{
// Register an attached property that enables apps to 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 enables delaying composition object creation until it's actually necessary.
var spotLight = Window.Current.Compositor.CreateSpotLight();
spotLight.InnerConeColor = Colors.Orange;
spotLight.OuterConeColor = Colors.Yellow;
spotLight.InnerConeAngleInDegrees = 30;
spotLight.OuterConeAngleInDegrees = 45;
spotLight.Offset = new System.Numerics.Vector3(30, 30, 200);
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;
}
}
Public NotInheritable Class OrangeSpotLight
Inherits XamlLight
' Register an attached property that enables apps to set a UIElement Or Brush as a target for this light type in markup.
Public Shared ReadOnly IsTargetProperty As DependencyProperty = DependencyProperty.RegisterAttached(
"IsTarget",
GetType(Boolean),
GetType(OrangeSpotLight),
New PropertyMetadata(Nothing, New PropertyChangedCallback(AddressOf OnIsTargetChanged)
)
)
Public Shared Sub SetIsTarget(target As DependencyObject, value As Boolean)
target.SetValue(IsTargetProperty, value)
End Sub
Public Shared Function GetIsTarget(target As DependencyObject) As Boolean
Return DirectCast(target.GetValue(IsTargetProperty), Boolean)
End Function
' Handle attached property changed to automatically target And untarget UIElements And Brushes.
Public Shared Sub OnIsTargetChanged(obj As DependencyObject, e As DependencyPropertyChangedEventArgs)
Dim isAdding = DirectCast(e.NewValue, Boolean)
If isAdding Then
If TypeOf obj Is UIElement Then
XamlLight.AddTargetElement(GetIdStatic(), TryCast(obj, UIElement))
ElseIf TypeOf obj Is Brush Then
XamlLight.AddTargetBrush(GetIdStatic(), TryCast(obj, Brush))
End If
Else
If TypeOf obj Is UIElement Then
XamlLight.RemoveTargetElement(GetIdStatic(), TryCast(obj, UIElement))
ElseIf TypeOf obj Is Brush Then
XamlLight.RemoveTargetBrush(GetIdStatic(), TryCast(obj, Brush))
End If
End If
End Sub
Protected Overrides Sub OnConnected(newElement As UIElement)
If CompositionLight Is Nothing Then
' OnConnected Is called when the first target UIElement Is shown on the screen. This enables delaying composition object creation until it's actually necessary.
Dim spotLight = Window.Current.Compositor.CreateSpotLight()
spotLight.InnerConeColor = Colors.Orange
spotLight.OuterConeColor = Colors.Yellow
spotLight.InnerConeAngleInDegrees = 30
spotLight.OuterConeAngleInDegrees = 45
spotLight.Offset = New System.Numerics.Vector3(30, 30, 200)
CompositionLight = spotLight
End If
End Sub
Protected Overrides Sub OnDisconnected(oldElement As UIElement)
' OnDisconnected Is called when there are no more target UIElements on the screen. The CompositionLight should be disposed when no longer required.
If CompositionLight IsNot Nothing Then
CompositionLight.Dispose()
CompositionLight = Nothing
End If
End Sub
Protected Overrides Function GetId() As String
Return GetIdStatic()
End Function
Private Shared Function GetIdStatic() As String
' This specifies the unique name of the light. In most cases you should use the type's FullName.
Return GetType(OrangeSpotLight).FullName
End Function
End Class
// OrangeSpotLight.h:
public ref class OrangeSpotLight sealed :
public Windows::UI::Xaml::Media::XamlLight
{
public:
OrangeSpotLight();
static property Windows::UI::Xaml::DependencyProperty^ IsTargetProperty
{
Windows::UI::Xaml::DependencyProperty^ get() { return m_isTargetProperty; }
};
static void SetIsTarget(Windows::UI::Xaml::DependencyObject^ target, bool value);
static bool GetIsTarget(Windows::UI::Xaml::DependencyObject^ target);
protected:
virtual void OnConnected(Windows::UI::Xaml::UIElement^ newElement) override;
virtual void OnDisconnected(Windows::UI::Xaml::UIElement^ oldElement) override;
virtual Platform::String^ GetId() override;
private:
static Windows::UI::Xaml::DependencyProperty^ m_isTargetProperty;
static void OnIsTargetChanged(Windows::UI::Xaml::DependencyObject^ obj, Windows::UI::Xaml::DependencyPropertyChangedEventArgs^ e);
inline static Platform::String^ GetIdStatic()
{
// This specifies the unique name of the light. In most cases you should use the type's FullName.
return OrangeSpotLight::typeid->FullName;
}
};
//OrangeSpotLight.cpp:
// Register an attached property that enables apps to set a UIElement or Brush as a target for this light type in markup.
DependencyProperty^ OrangeSpotLight::m_isTargetProperty = DependencyProperty::RegisterAttached(
"IsTarget",
bool::typeid,
OrangeSpotLight::typeid,
ref new PropertyMetadata(0.0, ref new PropertyChangedCallback(OnIsTargetChanged))
);
OrangeSpotLight::OrangeSpotLight()
{
}
void OrangeSpotLight::SetIsTarget(DependencyObject^ target, bool value)
{
target->SetValue(IsTargetProperty, value);
}
bool OrangeSpotLight::GetIsTarget(DependencyObject^ target)
{
return static_cast<bool>(target->GetValue(IsTargetProperty));
}
void OrangeSpotLight::OnIsTargetChanged(DependencyObject^ obj, DependencyPropertyChangedEventArgs^ e)
{
auto isAdding = static_cast<bool>(e->NewValue);
if (isAdding)
{
if (dynamic_cast<UIElement^>(obj))
{
XamlLight::AddTargetElement(GetIdStatic(), static_cast<UIElement^>(obj));
}
else if (dynamic_cast<Brush^>(obj))
{
XamlLight::AddTargetBrush(GetIdStatic(), static_cast<Brush^>(obj));
}
}
else
{
if (dynamic_cast<UIElement^>(obj))
{
XamlLight::RemoveTargetElement(GetIdStatic(), static_cast<UIElement^>(obj));
}
else if (dynamic_cast<Brush^>(obj))
{
XamlLight::RemoveTargetBrush(GetIdStatic(), static_cast<Brush^>(obj));
}
}
}
void OrangeSpotLight::OnConnected(UIElement^ newElement)
{
if (CompositionLight == nullptr)
{
// 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 = Window::Current->Compositor->CreateSpotLight();
spotLight->InnerConeColor = Colors::Orange;
spotLight->OuterConeColor = Colors::Yellow;
spotLight->InnerConeAngleInDegrees = 30;
spotLight->OuterConeAngleInDegrees = 45;
spotLight->Offset = float3(30, 30, 200);
CompositionLight = spotLight;
}
}
void OrangeSpotLight::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 != nullptr)
{
delete CompositionLight;
CompositionLight = nullptr;
}
}
Platform::String^ OrangeSpotLight::GetId()
{
return GetIdStatic();
}
The above light can then be applied to any XAML UIElement or Brush to light them. This example shows different potential usages:
<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
<Grid.Lights>
<!-- Attach a light, similar to setting a CompositionLight's CoordinateSpace property -->
<local:OrangeSpotLight />
</Grid.Lights>
<StackPanel>
<!-- this border will be lit by a OrangeSpotLight, but not its children -->
<Border BorderThickness="5">
<Border.BorderBrush>
<SolidColorBrush Color="White" local:OrangeSpotLight.IsTarget="true" />
</Border.BorderBrush>
<TextBlock Text="hello world" />
</Border>
<!-- this border and its content will be lit by OrangeSpotLight -->
<Border BorderThickness="5" BorderBrush="White" Background="White" local:OrangeSpotLight.IsTarget="true">
<TextBlock Text="hello world" Foreground="Gray" />
</Border>
<!-- this border will not be lit -->
<Border BorderThickness="5">
<Border.BorderBrush>
<SolidColorBrush Color="Green" />
</Border.BorderBrush>
<TextBlock Text="hello world" />
</Border>
</StackPanel>
</Grid>
Important
Setting UIElement.Lights in markup as shown in the above example is only supported for apps with a Minimum Version equal to the Windows 10 Creators Update or later. For apps that target earlier minimum versions, lights must be created in code-behind.
Remarks
You can use XamlLight to create custom lights.
For example, it can be used to create a light that applies a composition SpotLight to target elements to light them.
XamlLight provides methods for targeting UIElements or XAML Brushes, applying lights to trees of UIElements, and helping manage the lifetime of CompositionLight resources based on whether they're currently in use.
Custom XamlLights can be used in conjunction with custom Brushes derived from XamlCompositionBrushBase which use a SceneLightingEffect to controls the reflective properties of elements when being lit by a XamlLight.
Targeting objects
If you target a Brush with a XamlLight then the portions of any UIElements using that Brush will be lit by the light.
If you target a UIElement with a XamlLight then the entire UIElement and its child UIElements will all be lit by the light.
Targets can be added and removed by calling methods on a XamlLight instance. XamlLights can also define custom attached properties to add and remove targets from markup.
Managing resources
When creating a XamlLight, it's usually a good practice to delay creating a CompositionLight and any related resources until the light is being used. The OnConnected method is called when a XamlLight is first used to target an element or brush on screen, so you can override OnConnected to safely create resources only when they're needed.
It's also a good practice to dispose of composition resources when they're no longer in use. The OnDisconnected method is called when a XamlLight instance is no longer in use anywhere on the screen, so you can override OnDisconnected to safely dispose of resources. If the XamlLight is later used again after being disconnected then OnConnected will be called again.
Constructors
Properties
CompositionLight CompositionLight CompositionLight CompositionLight
Gets or sets the CompositionLight instance used to apply lighting effects.
protected : CompositionLight CompositionLight { get; set; }protected CompositionLight CompositionLight { get; set; }Protected ReadWrite Property CompositionLight As CompositionLight// This API is not available in Javascript.
An instance of a CompositionLight derived class used to apply lighting effects.
Remarks
It's usually a good practice to manage the lifetime of the CompositionLight object by delaying its creation until needed and disposing of it when no longer in use.
Methods
AddTargetBrush(String, Brush) AddTargetBrush(String, Brush) AddTargetBrush(String, Brush) AddTargetBrush(String, Brush)
Sets a Brush as a target of a XamlLight.
public : static void AddTargetBrush(PlatForm::String lightId, Brush brush)public static void AddTargetBrush(String lightId, Brush brush)Public Static Function AddTargetBrush(lightId As String, brush As Brush) As void// This API is not available in Javascript.
AddTargetElement(String, UIElement) AddTargetElement(String, UIElement) AddTargetElement(String, UIElement) AddTargetElement(String, UIElement)
Sets a UIElement as a target of a XamlLight.
public : static void AddTargetElement(PlatForm::String lightId, UIElement element)public static void AddTargetElement(String lightId, UIElement element)Public Static Function AddTargetElement(lightId As String, element As UIElement) As void// This API is not available in Javascript.
GetId() GetId() GetId() GetId()
Returns the identifier for the custom XamlLight type.
In most cases you should use a unique identifier to prevent conflicts. For example, you can use the FullName of your custom XamlLight type.
The identifier is used to add and remove Brushes and UIElements as targets for a specific light type.
protected : virtual PlatForm::String GetId()protected virtual string GetId()Protected Overridable Function GetId() As string// This API is not available in Javascript.
The identifier for the XamlLight.
OnConnected(UIElement) OnConnected(UIElement) OnConnected(UIElement) OnConnected(UIElement)
This method is automatically called when the XamlLight is first in use on the screen, or after being previously disconnected then used again.
This provides an opportunity to create resources such as the CompositionLight only when required.
OnDisconnected will be called when the XamlLight is no longer being used to light any UIElements or Brushes.
protected : virtual void OnConnected(UIElement newElement)protected virtual void OnConnected(UIElement newElement)Protected Overridable Function OnConnected(newElement As UIElement) As void// This API is not available in Javascript.
OnDisconnected(UIElement) OnDisconnected(UIElement) OnDisconnected(UIElement) OnDisconnected(UIElement)
This method is automatically called when the XamlLight is no longer in use anywhere on the screen.
This provides an opportunity to safely dispose of resources such as the CompositionLight when they aren't currently required.
OnConnected will be called again if the XamlLight is later used to light any UIElements or Brushes after being disconnected.
protected : virtual void OnDisconnected(UIElement oldElement)protected virtual void OnDisconnected(UIElement oldElement)Protected Overridable Function OnDisconnected(oldElement As UIElement) As void// This API is not available in Javascript.
RemoveTargetBrush(String, Brush) RemoveTargetBrush(String, Brush) RemoveTargetBrush(String, Brush) RemoveTargetBrush(String, Brush)
Stops a Brush from being a target of a XamlLight.
public : static void RemoveTargetBrush(PlatForm::String lightId, Brush brush)public static void RemoveTargetBrush(String lightId, Brush brush)Public Static Function RemoveTargetBrush(lightId As String, brush As Brush) As void// This API is not available in Javascript.
RemoveTargetElement(String, UIElement) RemoveTargetElement(String, UIElement) RemoveTargetElement(String, UIElement) RemoveTargetElement(String, UIElement)
Stops a UIElement from being a target of a XamlLight.
public : static void RemoveTargetElement(PlatForm::String lightId, UIElement element)public static void RemoveTargetElement(String lightId, UIElement element)Public Static Function RemoveTargetElement(lightId As String, element As UIElement) As void// This API is not available in Javascript.