Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Image Control #517

Merged
merged 6 commits into from
Feb 6, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
20 changes: 18 additions & 2 deletions src/Wpf.Ui.Gallery/Views/Pages/Media/ImagePage.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@
Title="ImagePage"
d:DataContext="{d:DesignInstance local:ImagePage,
IsDesignTimeCreatable=False}"
d:DesignHeight="450"
d:DesignHeight="700"
d:DesignWidth="800"
ui:Design.Background="{DynamicResource ApplicationBackgroundBrush}"
ui:Design.Foreground="{DynamicResource TextFillColorPrimaryBrush}"
Expand Down Expand Up @@ -42,14 +42,30 @@
Grid.Row="0"
Margin="0"
CodeText="<Image Height="100" Source="Assets\MyImage.jpg" />"
HeaderText="A basic Image from a local file">
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'd recommend leaving the default Image and adding a second one below, ui:Image, to show that there is a choice.

HeaderText="Standand Image from a local file.">
<controls:GalleryControlPresenter.Content>
<Image
Height="200"
HorizontalAlignment="Left"
Source="pack://application:,,,/Assets/pexels-johannes-plenio-1103970.jpg" />
</controls:GalleryControlPresenter.Content>
</controls:GalleryControlPresenter>

<controls:GalleryControlPresenter
Grid.Row="1"
Margin="0,32,0,0"
CodeText="&lt;ui:Image CornerRadius=&quot;4&quot; BorderBrush=&quot;#33000000&quot; Height=&quot;100&quot; Source=&quot;Assets\MyImage.jpg&quot; /&gt;"
HeaderText="WPF UI Image with rounded corners from a local file">
<controls:GalleryControlPresenter.Content>
<ui:Image
CornerRadius="4"
BorderBrush="#33000000"
BorderThickness="2"
Height="200"
HorizontalAlignment="Left"
Source="pack://application:,,,/Assets/pexels-johannes-plenio-1103970.jpg" />
</controls:GalleryControlPresenter.Content>
</controls:GalleryControlPresenter>
</Grid>
</Grid>
</ui:DynamicScrollViewer>
Expand Down
126 changes: 126 additions & 0 deletions src/Wpf.Ui/Controls/Image.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
// This Source Code Form is subject to the terms of the MIT License.
// If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
// Copyright (C) Leszek Pomianowski and WPF UI Contributors.
// All Rights Reserved.

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;

namespace Wpf.Ui.Controls;

/// <summary>
/// Represents an image with additional proproties for Borders and Rounded corners
/// </summary>
public class Image : Control
{
#region DependencyPropreties
/// <summary>
/// Gets/Sets the Source on this Image.
/// The Source property is the ImageSource that holds the actual image drawn.
/// </summary>
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register(nameof(Source), typeof(ImageSource), typeof(Image),
new FrameworkPropertyMetadata(null, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender, null, null),
null);

/// <summary>
/// DependencyProperty for CornerRadius property.
/// </summary>
public static readonly DependencyProperty CornerRadiusProperty =
DependencyProperty.Register(nameof(CornerRadius), typeof(CornerRadius), typeof(Image), new PropertyMetadata(new CornerRadius(0), new PropertyChangedCallback(OnCornerRadiusChanged)));

/// <summary>
/// DependencyProperty for StretchDirection property.
/// </summary>
/// <seealso cref="Viewbox.Stretch" />
public static readonly DependencyProperty StretchProperty = DependencyProperty.Register(
nameof(Stretch), typeof(Stretch), typeof(Image), new FrameworkPropertyMetadata(Stretch.Uniform, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender), null);

/// <summary>
/// DependencyProperty for Stretch property.
/// </summary>
public static readonly DependencyProperty StretchDirectionProperty = DependencyProperty.Register(
nameof(StretchDirection), typeof(StretchDirection), typeof(Image), new FrameworkPropertyMetadata(StretchDirection.Both, FrameworkPropertyMetadataOptions.AffectsMeasure | FrameworkPropertyMetadataOptions.AffectsRender), null);

/// <summary>
/// DependencyPropertyKey for InnerCornerRadius property.
/// </summary>
public static readonly DependencyPropertyKey InnerCornerRadiusPropertyKey = DependencyProperty.RegisterReadOnly(
nameof(InnerCornerRadius), typeof(CornerRadius), typeof(Image), new PropertyMetadata(new CornerRadius(0)));

/// <summary>
/// DependencyProperty for InnerCornerRadius property.
/// </summary>
public static readonly DependencyProperty InnerCornerRadiusProperty =
InnerCornerRadiusPropertyKey.DependencyProperty;
#endregion

#region Propreties
/// <summary>
/// Gets/Sets the Source on this Image.
/// The Source property is the ImageSource that holds the actual image drawn.
/// </summary>
public ImageSource Source
{
get => (ImageSource)GetValue(SourceProperty);
set => SetValue(SourceProperty, value);
}

/// <summary>
/// Gets/Sets the Stretch on this Image.
/// The Stretch property determines how large the Image will be drawn.
/// </summary>
public Stretch Stretch
{
get => (Stretch)GetValue(StretchProperty);
set => SetValue(StretchProperty, value);
}

/// <summary>
/// Gets/Sets the stretch direction of the Viewbox, which determines the restrictions on
/// scaling that are applied to the content inside the Viewbox. For instance, this property
/// can be used to prevent the content from being smaller than its native size or larger than
/// its native size.
/// </summary>
public StretchDirection StretchDirection
{
get => (StretchDirection)GetValue(StretchDirectionProperty);
set => SetValue(StretchDirectionProperty, value);
}

/// <summary>
/// The CornerRadius property allows users to control the roundness of the corners independently by
/// setting a radius value for each corner. Radius values that are too large are scaled so that they
/// smoothly blend from corner to corner.
/// </summary>
public CornerRadius CornerRadius
{
get => (CornerRadius)GetValue(CornerRadiusProperty);
set => SetValue(CornerRadiusProperty, value);
}

/// <summary>
/// The CornerRadius for the inner image's Mask.
/// </summary>
internal CornerRadius InnerCornerRadius => (CornerRadius)GetValue(InnerCornerRadiusProperty);
#endregion

#region Methods
private static void OnCornerRadiusChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var thickness = (Thickness)d.GetValue(BorderThicknessProperty);
var outerRarius = (CornerRadius)e.NewValue;

//Inner radius = Outer radius - thickenss/2
d.SetValue(InnerCornerRadiusPropertyKey,
new CornerRadius(
topLeft: Math.Max(0, (int)Math.Round(outerRarius.TopLeft - thickness.Left / 2, 0)),
topRight: Math.Max(0, (int)Math.Round(outerRarius.TopRight - thickness.Top / 2, 0)),
bottomRight: Math.Max(0, (int)Math.Round(outerRarius.BottomRight - thickness.Right / 2, 0)),
bottomLeft: Math.Max(0, (int)Math.Round(outerRarius.BottomLeft - thickness.Bottom / 2, 0)))
);
}
#endregion
}
48 changes: 48 additions & 0 deletions src/Wpf.Ui/Styles/Controls/Image.xaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,48 @@
<!--
This Source Code Form is subject to the terms of the MIT License.
If a copy of the MIT was not distributed with this file, You can obtain one at https://opensource.org/licenses/MIT.
Copyright (C) Leszek Pomianowski and WPF UI Contributors.
All Rights Reserved.

Based on Microsoft XAML for Win UI
Copyright (c) Microsoft Corporation. All Rights Reserved.
-->

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:Wpf.Ui.Controls">
<Style x:Key="DefaultImageStyle" TargetType="{x:Type controls:Image}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type controls:Image}">
<Border VerticalAlignment="Center" HorizontalAlignment="Center"
BorderThickness="{TemplateBinding BorderThickness}"
BorderBrush="{TemplateBinding BorderBrush}"
CornerRadius="{TemplateBinding CornerRadius}"
Background="{TemplateBinding Background}"
ClipToBounds="True">

<Image Source="{TemplateBinding Source}"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Stretch="{TemplateBinding Stretch}"
StretchDirection="{TemplateBinding StretchDirection}">
<Image.OpacityMask>
<VisualBrush>
<VisualBrush.Visual>
<Border Height="{TemplateBinding ActualHeight}"
Width="{TemplateBinding ActualWidth}"
Background="White"
CornerRadius="{TemplateBinding InnerCornerRadius}" />
</VisualBrush.Visual>
</VisualBrush>
</Image.OpacityMask>
</Image>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

<Style BasedOn="{StaticResource DefaultImageStyle}" TargetType="{x:Type controls:Image}" />
</ResourceDictionary>
1 change: 1 addition & 0 deletions src/Wpf.Ui/Styles/Wpf.Ui.xaml
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,7 @@
<ResourceDictionary Source="pack://application:,,,/Wpf.Ui;component/Styles/Controls/NavigationViewBreadcrumb.xaml" />
<ResourceDictionary Source="pack://application:,,,/Wpf.Ui;component/Styles/Controls/BreadcrumbBar.xaml" />
<ResourceDictionary Source="pack://application:,,,/Wpf.Ui;component/Styles/Controls/NavigationView.xaml" />
<ResourceDictionary Source="pack://application:,,,/Wpf.Ui;component/Styles/Controls/Image.xaml" />

<ResourceDictionary Source="pack://application:,,,/Wpf.Ui;component/Styles/Controls/TextBlock.xaml" />
<ResourceDictionary Source="pack://application:,,,/Wpf.Ui;component/Styles/Controls/ScrollBar.xaml" />
Expand Down