Элемент управления Silverlight с параметром «Измерить / желаемый размер» с растяжением изображения из среднего пользовательского контроля - PullRequest
3 голосов
/ 22 мая 2011

У меня есть пользовательский элемент управления, над которым я работаю, и он работает нормально сам по себе, однако, когда это сетка, где задается ширина, я получаю такие ошибки, как:

Переопределение измерения макета элемента '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

}

Generic.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, основанного на UIImage от iOS и Android 9-Patch, о котором я слышал, но не видел. Кто-нибудь может помочь? Есть ли альтернатива тому, что я делаю, чтобы сделать это как один элемент изображения, который может растягиваться в середине, если это решение.

1 Ответ

1 голос
/ 22 мая 2011

Я могу дать общее представление о том, что происходит, и некоторые предложения о том, как действовать. Как правило, свойства Control.Width и Control.Height предназначены для пользователя , а не для вас. Элемент управления должен принимать эти значения как входные данные и использовать их как часть процесса компоновки, чтобы влиять на результирующие свойства ActualWidth и ActualHeight.

Теперь, даже если вы никогда не намереваетесь позволить пользователю указать Width или Height в XAML, проблема остается той же. Вы, как автор элемента управления, должны сообщить системе макета свой желаемый размер во время вызовов методов MeasureOverride и ArrangeOverride, как описано здесь:

В частности, поскольку вы не переопределили MeasureOverride, поведение по умолчанию возвращает желаемый размер первого визуального дочернего элемента, который в вашем случае будет Grid, размер которого не указан, и поэтому он хочет быть как можно большим, то есть бесконечным.

Итак, решение звучит просто: посчитайте ваши размеры в MeasureOverride и ArrangeOverride вместо OnApplyTemplate, верно? Проблема в том, что у вас может не быть всей необходимой информации в нужное время. Если вы этого не сделаете, то вам нужно будет просто вернуть наиболее подходящее предположение для желаемого размера, а затем , когда вы получите правильную информацию , форсировать новый проход макета, чтобы MeasureOverride снова вызывался. Ссылка выше и документация в целом описывает, как это сделать.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...