c# - 具有测量/所需尺寸问题的 Silverlight 控件,图像从中间用户控件拉伸(stretch)

标签 c# silverlight xaml layout custom-controls

我有一个我正在处理的自定义控件,它自己可以正常工作,但是当它是设置宽度的网格时,我会收到如下错误:

元素“Microsoft.Windows.Design.Platform.SilverlightViewProducer+SilverlightContentHost”的布局测量覆盖不应返回 PositiveInfinity 作为其 DesiredSize,即使 Infinity 作为可用大小传入也是如此。

这些错误只发生在我的应用程序中,而不是我的测试工具中 - 但我不能在这里发布前者,但这里可能有一些我遗漏的东西 - 可能能够弥补这个问题 - 但如果有人可以帮助它会很棒

这是类代码:

public class UXImage : Control
    {
        #region Private Constants
        private const string RightImageControl = "RightImage";
        private const string MiddleImageControl = "MiddleImage";
        private const string LeftImageControl = "LeftImage";
        #endregion

    #region Private Members
    private int sourceHeight;
    private int sourceWidth;
    private int middleWidth = 1;
    WriteableBitmap crop;
    TransformGroup transform = new TransformGroup();
    TranslateTransform position = new TranslateTransform();
    ScaleTransform scale = new ScaleTransform();
    // Controls
    private Image image = new Image();
    private Image rightImageControl;
    private Image middleImageControl;
    private Image leftImageControl;
    #endregion

    #region Dependency Properties

    public static readonly DependencyProperty SourceProperty =
    DependencyProperty.Register("Source", typeof(BitmapSource),
    typeof(UXImage), null);

    public static readonly DependencyProperty RightCapWidthProperty =
    DependencyProperty.Register("RightCapWidth", typeof(int),
    typeof(UXImage), null);

    #endregion

    #region Public Properties

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

    public int RightCapWidth
    {
        get { return (int)GetValue(RightCapWidthProperty); }
        set
        {
            SetValue(RightCapWidthProperty, value);
        }
    }
    #endregion

    #region Public Methods

    /// <summary>
    /// On Apply Template
    /// </summary>
    public override void OnApplyTemplate()
    {
        base.OnApplyTemplate();
        sourceHeight = Source.PixelHeight;
        sourceWidth = Source.PixelWidth;
        image.Source = Source;
        // Right Element
        rightImageControl = (Image)GetTemplateChild(RightImageControl);
        crop = new WriteableBitmap(RightCapWidth, sourceHeight);
        position.X = -sourceWidth + RightCapWidth;
        crop.Render(image, position);
        crop.Invalidate();
        rightImageControl.Source = crop;
        rightImageControl.Width = RightCapWidth;
        // Middle Element
        middleImageControl = (Image)GetTemplateChild(MiddleImageControl);
        crop = new WriteableBitmap(middleWidth, sourceHeight);
        position.X = -sourceWidth + RightCapWidth + middleWidth;
        crop.Render(image, position);
        crop.Invalidate();
        middleImageControl.Source = crop;
        middleImageControl.Height = sourceHeight;
        // Left Element
        leftImageControl = (Image)GetTemplateChild(LeftImageControl);
        crop = new WriteableBitmap(sourceWidth - RightCapWidth - middleWidth, sourceHeight);
        position.X = 0;
        crop.Render(image, position);
        crop.Invalidate();
        leftImageControl.Source = crop;
        leftImageControl.Height = sourceHeight;
        this.Height = sourceHeight;
        this.Width = sourceWidth;
    }

    public UXImage()
    {
        DefaultStyleKey = typeof(UXImage);
    }
    #endregion

}

通用.xaml

<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:vsm="clr-namespace:System.Windows;assembly=System.Windows"
xmlns:local="clr-namespace:UXLibrary">
<Style TargetType="local:UXImage">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="local:UXImage">
                    <Grid>
                        <Grid.ColumnDefinitions>
                            <ColumnDefinition Width="Auto"/>
                            <ColumnDefinition Width="*"/>
                            <ColumnDefinition Width="Auto"/>
                        </Grid.ColumnDefinitions>
                        <Image x:Name="LeftImage" Stretch="Uniform" Source="{TemplateBinding Source}" Grid.Column="0"/>
                        <Image x:Name="MiddleImage" Stretch="Fill" Grid.Column="1"/>
                        <Image x:Name="RightImage" Stretch="Uniform" Grid.Column="2"/>
                    </Grid>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
</ResourceDictionary>

用法:

<ux:UXImage RightCapWidth="10" Source="Images/example.png"/>

我还没有在 Silverlight 中看到过这样的控件,它基于我听说过但未见过的 iOS 和 Android 9-Patch 中的 UIImage。 谁能帮忙?如果这是一个解决方案,是否有替代方法来做我正在做的事情,作为一个可以在中间拉伸(stretch)的图像元素。

最佳答案

我可以提供有关正在发生的事情的基本概念以及有关如何进行的一些建议。一般而言,Control.WidthControl.Height 属性由用户提供,而不是您。 控件 应该将这些值作为输入 并将它们用作布局过程的一部分以影响生成的ActualWidthActualHeight 属性。

现在,即使您从未打算让用户在 XAML 中指定 WidthHeight,问题仍然相同。作为控件作者,您应该在 MeasureOverrideArrangeOverride 方法调用期间告诉布局系统您想要的大小,如下所述:

特别是,由于您没有覆盖 MeasureOverride,默认行为是返回第一个视觉子项的所需大小,在您的情况下将是 Grid ,其大小未指定,因此希望尽可能大,即无限大。

因此,解决方案听起来很简单:在 MeasureOverrideArrangeOverride 而不是 OnApplyTemplate 中计算尺寸,对吧?问题是,您可能无法在正确的时间获得所需的全部信息。如果您不这样做,那么您将需要简单地返回您对所需尺寸的最佳猜测,然后当您获得正确的信息时,强制执行新的布局传递,以便 MeasureOverride将再次被调用。上面的链接和一般文档描述了如何执行此操作。

关于c# - 具有测量/所需尺寸问题的 Silverlight 控件,图像从中间用户控件拉伸(stretch),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6088200/

相关文章:

c# - 将 WPF 网格更改为原点位于左下角

c# - 将实体连同子实体一起转换为 DTO

Silverlight 4 - 安装是否需要管理员权限?

javascript - Silverlight HTML-JS-DOM 桥 : Real world use cases?

.net - IDataErrorInfo.Error 应该检查每个属性吗?

c# - WPF ListViewItem 多个事件通过 AttachedCommandBehaviour

c# - 为什么 Unity 会在此处抛出错误 CS0136 而 Visual Studio 2019 不会?

c# - 硬编码文本和格式

C# + 模拟服务层?

C# 应用程序 - 如何在 xaml 表单中显示网站?