문제

런타임에 cruppedbitmap의 Sourcerect 속성을 변경하려고 할 때 아무 일도 일어나지 않습니다. 오류가 없으며 속성 값이 실제로 변경되지 않습니다.

스프라이트 애니메이션을하려고합니다. 스프리 시트가 포함 된 비트 맵스 소스가 있습니다. 여기에는 스프라이트를 위해 다른 포즈의 그리드를 포함하는 단일 비트 맵입니다. 그런 다음 스프리 시트를 소스로 사용하는 CruppedBitMap과 스프리 시트에서 포즈 중 하나를 끌어내는 출처가 있습니다. 런타임에 애니메이션을 원할 때 CruppedBitMap의 Sourcerect 속성을 변경하여 더 큰 비트 맵에서 다른 포즈를 꺼내려고합니다. 그러나 위에서 언급했듯이 새로운 속성 가치는 단순히 고수하지 않습니다. 그것은 가장 이상한 것입니다.

다음은 샘플 XAML입니다.

<UserControl.Resources>
    <BitmapImage x:Key="spritesheet" UriSource="Sprites/elf.png"/>
</UserControl.Resources>
<Image>
    <Image.Source>
        <CroppedBitmap x:Name="image" Source="{StaticResource spritesheet}"
                       SourceRect="240 640 240 320"/>
    </Image.Source>
</Image>

그리고 CodeBehind는 다음을 시도합니다.

var newRect = new Int32Rect(...);
Debug.WriteLine("             Before: " + image.SourceRect);
Debug.WriteLine("Assigning new value: " + newRect);
image.SourceRect = newRect;
Debug.WriteLine("              After: " + image.SourceRect);

이 디버그 출력을 제공합니다.

             Before: 240,640,240,320
Assigning new value: 240,0,240,320
              After: 240,640,240,320

따라서 실제로 새 사각형 (y = 0)을 속성에 할당합니다. 예외는 없습니다. 그러나 그 후, 속성 값은 단순히 변하지 않았습니다 (Y는 여전히 640입니다).

이런 일이 발생하는 이유와이를 고치는 방법에 대한 아이디어가 있습니까?

도움이 되었습니까?

해결책

나는 결국 답을 찾았다. 문서에서 CrpedpitBitMap:

CruppedBitMap은 여러 속성에서의 초기화를 최적화하기 위해 isupportinitialize 인터페이스를 구현합니다. 객체 초기화 중에 만 속성 변경이 발생할 수 있습니다. 초기화가 시작되었음을 알리고 초기화가 완료되었음을 알리기 위해 ENDINIT가 시작되었음을 알리십시오. 초기화 후 속성 변경은 무시됩니다. (강조 광산)

재미를 위해, 나는 method () .. endinit () 호출을 내 메소드에 추가하여 수정할 수 있는지 확인했습니다. 놀랍게도, 나는 무효화 외과를 얻었습니다 ( "초기화 상태를 두 번 이상 설정할 수 없습니다").

따라서 CrpedpedBitMap은 효과적입니다 불변. (그러나 그들은 자신의 동결성 시스템을 무시했는데, 내가 뭔가 잘못하고 있다고 말하면서 예외를 던지고 더 많은 것을 구현했습니다. 놀라운 대신에.)

즉, Sourcerect 속성을 변경하는 데 아무것도 없음을 의미합니다. 스프리 시트 내의 각 하위 이미지에 대해 별도의 CrpedpedBitMap 인스턴스를 만들어야합니다.

다른 팁

다음은 이것을 다루는 대체 방법입니다.
a를 사용하는 대신 CroppedBitmap, 전체 소스 이미지를 사용하지만 :

  1. 설정 image.RenderTransform 볼 수있는 영역을 조정합니다.
  2. 설정을 설정하십시오 Image.Clip 필요한 경우 원치 않는 이미지의 일부를 표시하지 않도록하십시오.

이것은 당신이 계속 새로운 것을 만들 필요가 없다는 것을 의미합니다 CroppedBitmaps, 당신은 변환을 조정할 수 있습니다.
내 테스트에서 나는 속도가 어느 쪽이든 그렇게하는 데 아무런 차이가 없었습니다.

완전성을 위해 여기에 내가 제안한 것을 수행하도록 코드를 조정하는 방법은 다음과 같습니다.

<Image RenderTransform="1, 0, 0, 1, -240, -640">
  <!-- Still include your Image.Source here, just not as a CroppedBitmap -->
  <Image.Clip>
    <RectangleGeometry Rect="0, 0, 240, 320" />
  </Image.Clip>
</Image>

그런 다음 나중에 조정하는 것과 동등한 것을 요청합니다. SourceRect 이다:

image.RenderTransform = new MatrixTransform(1d, 0d, 0d, 1d, -240d, 0d);

다음은 사용 방법이 있습니다 IMultiValueConverter:

<Image>
    <Image.Source>
        <MultiBinding Converter="{x:Static local:SourceAndRectToCroppedBitmapConverter.Default}">
            <Binding Path="FileName" />
            <Binding Path="CropRect" />
        </MultiBinding>
    </Image.Source>

using System;
using System.Globalization;
using System.Windows;
using System.Windows.Data;
using System.Windows.Media;
using System.Windows.Media.Imaging;

public class SourceAndRectToCroppedBitmapConverter : IMultiValueConverter
{
    public static readonly SourceAndRectToCroppedBitmapConverter Default = new SourceAndRectToCroppedBitmapConverter();

    private static readonly ImageSourceConverter Converter = new ImageSourceConverter();

    public object Convert(object[] values, Type targetType, object parameter, CultureInfo culture)
    {
        if (values[0] is string text)
        {
            return new CroppedBitmap((BitmapSource)Converter.ConvertFrom(values[0]), (Int32Rect)values[1]);
        }

        return new CroppedBitmap((BitmapSource)values[0], (Int32Rect)values[1]);
    }

    object[] IMultiValueConverter.ConvertBack(object value, Type[] targetTypes, object parameter, CultureInfo culture)
    {
        throw new NotSupportedException();
    }
}

잠재적으로 가난한 성능.

라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top