Практическое руководство. Создание отражения
В этой статье показано, как использовать для VisualBrush создания отражения. Так как можно использовать VisualBrush для отображения существующего визуального элемента, это позволяет создавать интересные визуальные эффекты, например отражения и увеличение.
Пример XAML
В следующем примере используется кисть VisualBrush для создания отражения объекта Border, содержащего несколько элементов.
<StackPanel Margin="25" Height="400">
<!-- The object to reflect. -->
<Border Name="ReflectedVisual" Width="400">
<Border.Background>
<LinearGradientBrush StartPoint="0,0.5" EndPoint="1,0.5">
<GradientStop Offset="0.0" Color="#CCCCFF" />
<GradientStop Offset="1.0" Color="White" />
</LinearGradientBrush>
</Border.Background>
<StackPanel Orientation="Horizontal" Margin="10">
<TextBlock TextWrapping="Wrap" Width="200" Margin="10">
Lorem ipsum dolor sit amet, consectetuer adipiscing elit.
Suspendisse vel ante. Donec luctus tortor sit amet est.
Nullam pulvinar odio et wisi.
Pellentesque quis magna. Sed pellentesque.
</TextBlock>
<StackPanel>
<Ellipse Margin="10" Height="50" Width="50" Fill="Black" />
<Ellipse Margin="10" Height="50" Width="50" Fill="Purple" />
</StackPanel>
</StackPanel>
</Border>
<Rectangle Height="1" Fill="Gray" HorizontalAlignment="Stretch" />
<!-- The object to contain the reflection.-->
<Rectangle DataContext="{Binding ElementName=ReflectedVisual}"
Height="{Binding Path=ActualHeight}"
Width="{Binding Path=ActualWidth}">
<Rectangle.Fill>
<!-- Creates the reflection. -->
<VisualBrush Opacity="0.75" Stretch="None"
Visual="{Binding}">
<VisualBrush.RelativeTransform>
<!-- Flip the reflection. -->
<TransformGroup>
<ScaleTransform ScaleX="1" ScaleY="-1" />
<TranslateTransform Y="1" />
</TransformGroup>
</VisualBrush.RelativeTransform>
</VisualBrush>
</Rectangle.Fill>
<Rectangle.OpacityMask>
<LinearGradientBrush StartPoint="0.5,0" EndPoint="0.5,1">
<GradientStop Color="#FF000000" Offset="0.0" />
<GradientStop Color="#33000000" Offset="0.5" />
<GradientStop Color="#00000000" Offset="0.75" />
</LinearGradientBrush>
</Rectangle.OpacityMask>
<Rectangle.Effect>
<BlurEffect Radius="1.5" />
</Rectangle.Effect>
</Rectangle>
</StackPanel>
Пример на основе кода
В следующем примере используется кисть VisualBrush для создания отражения объекта Border, содержащего несколько элементов. Этот код выполняется в обработчике Window.Loaded
событий:
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var container = new StackPanel();
container.Height = 400;
container.Margin = new Thickness(25);
// Visual Element that will be reflected
var visualElement = new Border
{
Width = 400,
Background = new LinearGradientBrush(
(Color)ColorConverter.ConvertFromString("#CCCCFF"),
Colors.White,
new Point(0.0, 0.5),
new Point(1.0, 0.5))
};
// Stack panel inside parent border
{
var visualElementChild1 = new StackPanel
{
Orientation = Orientation.Horizontal,
Margin = new Thickness(10)
};
// Stack panel content
{
var paragraphContent = new TextBlock
{
Text = "Lorem ipsum dolor sit amet, consectetuer adipiscing elit.\nSuspendisse vel ante. Donec luctus tortor sit amet est.\nNullam pulvinar odio et wisi.\nPellentesque quis magna. Sed pellentesque.",
Width = 200,
Margin = new Thickness(10),
TextWrapping = TextWrapping.Wrap
};
var ellipsePanel = new StackPanel();
ellipsePanel.Children.Add(new Ellipse() { Margin = new Thickness(10), Height = 50, Width = 50, Fill = Brushes.Black });
ellipsePanel.Children.Add(new Ellipse() { Margin = new Thickness(10), Height = 50, Width = 50, Fill = Brushes.Purple });
// Add to parent
visualElementChild1.Children.Add(paragraphContent);
visualElementChild1.Children.Add(ellipsePanel);
}
// Add to parent
visualElement.Child = visualElementChild1;
}
// Add visual to reflect to container
container.Children.Add(visualElement);
// Line separator
container.Children.Add(new Rectangle() { Height = 1, Fill = Brushes.Gray, HorizontalAlignment = HorizontalAlignment.Stretch });
// Reflection
Rectangle reflection = new Rectangle();
reflection.DataContext = visualElement;
reflection.SetBinding(Rectangle.WidthProperty, "ActualWidth");
reflection.SetBinding(Rectangle.HeightProperty, "ActualHeight");
// Create the reflection effect
var transform = new TransformGroup();
transform.Children.Add(new ScaleTransform(1, -1));
transform.Children.Add(new TranslateTransform(0, 1));
var reflectedBrush = new VisualBrush();
reflectedBrush.RelativeTransform = transform;
reflectedBrush.Opacity = 0.75;
reflectedBrush.Stretch = Stretch.None;
reflectedBrush.Visual = visualElement;
// Add the reflection effect
reflection.Fill = reflectedBrush;
reflection.OpacityMask = new LinearGradientBrush(
new GradientStopCollection(new[]
{
new GradientStop((Color)ColorConverter.ConvertFromString("#FF000000"), 0.0),
new GradientStop((Color)ColorConverter.ConvertFromString("#33000000"), 0.5),
new GradientStop((Color)ColorConverter.ConvertFromString("#00000000"), 0.75)
}),
new Point(0.5, 0),
new Point(0.5, 1));
reflection.Effect = new BlurEffect() { Radius = 1.5 };
// Add the reflection to the container
container.Children.Add(reflection);
// Set the container as the content of this window
Content = container;
}
Private Sub Window_Loaded(sender As Object, e As RoutedEventArgs)
Dim container As New StackPanel With {.Height = 400, .Margin = New Thickness(25)}
' Visual Element that will be reflected
Dim visualElement As New Border With {
.Width = 400,
.Background = New LinearGradientBrush(
ColorConverter.ConvertFromString("#CCCCFF"),
Colors.White,
New Point(0.0, 0.5),
New Point(1.0, 0.5))
}
' Stack panel inside parent border
Dim visualElementChild1 As New StackPanel With {
.Orientation = Orientation.Horizontal,
.Margin = New Thickness(10)
}
' Stack panel content
Dim paragraphContent As New TextBlock With {
.Text = $"Lorem ipsum dolor sit amet, consectetuer adipiscing elit.{vbNewLine}Suspendisse vel ante. Donec luctus tortor sit amet est.{vbNewLine}Nullam pulvinar odio et wisi.{vbNewLine}Pellentesque quis magna. Sed pellentesque.",
.Width = 200,
.Margin = New Thickness(10),
.TextWrapping = TextWrapping.Wrap
}
Dim ellipsePanel = New StackPanel
ellipsePanel.Children.Add(New Ellipse() With {.Margin = New Thickness(10), .Height = 50, .Width = 50, .Fill = Brushes.Black})
ellipsePanel.Children.Add(New Ellipse() With {.Margin = New Thickness(10), .Height = 50, .Width = 50, .Fill = Brushes.Purple})
' Add stack panel content
visualElementChild1.Children.Add(paragraphContent)
visualElementChild1.Children.Add(ellipsePanel)
' Add stack panel to border
visualElement.Child = visualElementChild1
' Add visual to reflect to container
container.Children.Add(visualElement)
' Line separator
container.Children.Add(New Rectangle() With {.Height = 1, .Fill = Brushes.Gray, .HorizontalAlignment = HorizontalAlignment.Stretch})
' Reflection
Dim reflection As New Rectangle
reflection.DataContext = visualElement
reflection.SetBinding(Rectangle.WidthProperty, "ActualWidth")
reflection.SetBinding(Rectangle.HeightProperty, "ActualHeight")
' Create the reflection effect
Dim Transform = New TransformGroup
Transform.Children.Add(New ScaleTransform(1, -1))
Transform.Children.Add(New TranslateTransform(0, 1))
Dim reflectedBrush As New VisualBrush With {
.RelativeTransform = Transform,
.Opacity = 0.75,
.Stretch = Stretch.None,
.Visual = visualElement
}
' Add the reflection effect
reflection.Fill = reflectedBrush
reflection.OpacityMask = New LinearGradientBrush(
New GradientStopCollection(
{
New GradientStop(ColorConverter.ConvertFromString("#FF000000"), 0.0),
New GradientStop(ColorConverter.ConvertFromString("#33000000"), 0.5),
New GradientStop(ColorConverter.ConvertFromString("#00000000"), 0.75)
}),
New Point(0.5, 0),
New Point(0.5, 1))
reflection.Effect = New BlurEffect() With {.Radius = 1.5}
' Add the reflection to the container
container.Children.Add(reflection)
' Set the container as the content of this window
Content = container
End Sub
См. также
.NET Desktop feedback