C# XAML相当于CSS中的对象位置

C# XAML相当于CSS中的对象位置,c#,wpf,css,xaml,C#,Wpf,Css,Xaml,我正在开发一个WPF应用程序,它显示一个项目列表,每个项目都有一个与之关联的小图像。我从API接收图像url和由0-1之间的两个数字表示的焦点。 web应用程序只需将这些数字乘以100,并使用它们设置对象位置CSS属性,如下所示: focusPoints: 0.9/0.5 变成 object-position: 90% 50%; 我的问题是如何在WPF中使用它?并没有类似于对象位置的属性,尽管我认为我只需要使用Margin,但它似乎并没有那个么简单。 我给你举个例子。假设我有一张人脸的照片,

我正在开发一个WPF应用程序,它显示一个项目列表,每个项目都有一个与之关联的小图像。我从API接收图像url和由0-1之间的两个数字表示的焦点。 web应用程序只需将这些数字乘以100,并使用它们设置对象位置CSS属性,如下所示:

focusPoints: 0.9/0.5
变成

object-position: 90% 50%;
我的问题是如何在WPF中使用它?并没有类似于对象位置的属性,尽管我认为我只需要使用Margin,但它似乎并没有那个么简单。 我给你举个例子。假设我有一张人脸的照片,但是这张脸不是以图像为中心,而是在右边。如果裁剪图像,则将裁剪面,但如果在面上设置焦点,则将从左侧裁剪图像,而不是从每条边剪切。这就是焦点的使用方式,在CSS中只使用对象位置,但在XAML中,我想我必须做一些数学计算,以确定什么是边距或画布。上/左。 此外,还介绍了如何在图像中设置焦点。

CSS对象位置的工作原理 它将img html元素的宽度/高度与实际图片的宽度/高度进行比较。这些差异被认为是“100%”。因此,如果容器(img元素)的宽度为100px,图片的宽度为160px,则差值为60px,即“100%”。如果我们将“水平对象位置”值设置为50%,它将在容器内向左移动图片30px(60px的50%),从而使图片水平居中

WPF控制 在画布中操纵图像的自定义控件

[TemplatePart(Name = ImagePart, Type = typeof(Image))]
[TemplatePart(Name = CanvasPart, Type = typeof(Canvas))]
public class PositionableImage : Control
{
    private const string ImagePart = "PART_Image";
    private const string CanvasPart = "PART_Canvas";

    static PositionableImage()
    {
        DefaultStyleKeyProperty.OverrideMetadata(
            typeof(PositionableImage),
            new FrameworkPropertyMetadata(typeof(PositionableImage)));
    }

    public string Source
    {
        get { return (string)GetValue(SourceProperty); }
        set { SetValue(SourceProperty, value); }
    }

    public static readonly DependencyProperty SourceProperty = DependencyProperty.Register(
        "Source",
        typeof(string),
        typeof(PositionableImage),
        new PropertyMetadata(string.Empty));

    public double HorizontalPosition
    {
        get { return (double)GetValue(HorizontalPositionProperty); }
        set { SetValue(HorizontalPositionProperty, value); }
    }

    public static readonly DependencyProperty HorizontalPositionProperty = DependencyProperty.Register(
        "HorizontalPosition",
        typeof(double),
        typeof(PositionableImage),
        new PropertyMetadata(0d, OnHorizontalPositionChanged));

    private static void OnHorizontalPositionChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        PositionableImage pi = d as PositionableImage;
        if (pi == null) return;

        if (!double.TryParse(e.NewValue.ToString(), out double newPosition)) return;

        pi.UpadateHorizontalPosition(newPosition);
    }

    public double VerticalPosition
    {
        get { return (double)GetValue(VerticalPositionProperty); }
        set { SetValue(VerticalPositionProperty, value); }
    }

    public static readonly DependencyProperty VerticalPositionProperty = DependencyProperty.Register(
        "VerticalPosition",
        typeof(double),
        typeof(PositionableImage),
        new PropertyMetadata(0d, OnVerticalPositionSizeChanged));

    private static void OnVerticalPositionSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        PositionableImage pi = d as PositionableImage;
        if (pi == null) return;

        if (!double.TryParse(e.NewValue.ToString(), out double newPosition)) return;

        pi.UpdateVerticalPosition(newPosition);
    }

    private Image image;
    private Canvas canvas;

    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();

        if (this.canvas != null)
            this.canvas.SizeChanged -= OnCanvasSizeChanged;

        this.image = this.GetTemplateChild(ImagePart) as Image;
        this.canvas = this.GetTemplateChild(CanvasPart) as Canvas;

        if (this.canvas != null)
            this.canvas.SizeChanged += OnCanvasSizeChanged;
    }

    private void OnCanvasSizeChanged(object sender, SizeChangedEventArgs e)
    {
        if (e.HeightChanged)
            this.UpdateVerticalPosition(VerticalPosition);

        if (e.WidthChanged)
            this.UpadateHorizontalPosition(HorizontalPosition);
    }

    private void UpadateHorizontalPosition(double position)
    {
        if (this.image == null || this.canvas == null) return;

        double offset = this.CalculateOffset(this.canvas.ActualWidth, this.image.ActualWidth, position);

        this.image.SetCurrentValue(Canvas.LeftProperty, offset);
    }

    private void UpdateVerticalPosition(double position)
    {
        if (this.image == null || this.canvas == null) return;

        double offset = this.CalculateOffset(this.canvas.ActualHeight, this.image.ActualHeight, position);

        this.image.SetCurrentValue(Canvas.TopProperty, offset);
    }

    private double CalculateOffset(double canvasLength, double imageLength, double position)
    {
        return -(imageLength - canvasLength) * position;
    }
}
模板

<Style TargetType="{x:Type local:PositionableImage}">
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="{x:Type local:PositionableImage}">
                <Canvas x:Name="PART_Canvas"
                        Width="{TemplateBinding Width}"
                        Height="{TemplateBinding Height}"
                        Background="{TemplateBinding Background}"
                        ClipToBounds="True">
                    <Image x:Name="PART_Image"
                           Source="{Binding Path=Source, RelativeSource={RelativeSource TemplatedParent}}"/>
                </Canvas>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

用法


使用中


你的问题有点不清楚。如果要使用坐标显式定位元素,应该使用画布:定位元素不是问题,实现焦点是问题。焦点?请更具体一些。对不起,我用一个例子编辑了我的问题。也许你在找剪辑属性?解释对象位置是如何工作的已经足够了,但是非常感谢您提供的源代码,它正是我想要的@他们说不客气。我有网络开发的背景,所以和他们结婚很有趣。
<local:PositionableImage Width="60"
                         Height="60"
                         Source="H:\test.jpg"
                         HorizontalPosition=".5"
                         VerticalPosition=".5"/>