프로그래밍/WPF

[WPF] Converter를 이용한 Binding Image Source

흔한티벳여우 2023. 3. 23. 11:34
반응형

일반적으로 Image 컨트롤에 Image의 Path를 string 형태로 바인딩하면 화면에 이미지가 나온다.

그러나 이렇게 되면 해당 이미지를 프로그램이 계속 점유하고 있게 된다.

간단한 예를 들어보자 한쪽에는 한 화면에 좌측은 이미지가 있고, 오른쪽은 ListView에 이미지들의 나온다고 하고, ListView에서 Image의 이름을 선택하면 좌측에 해당 이미지가 보여주는 프로그램이 있다고 하자.

 

일반적인 바인딩의 경우 아래와 같이 할것이다.

<Image x:Name="img"
        Source="{Binding ImagePath}">
</Image>

선택한 이미지를 ImagePath라는 string에 바인딩 처리하여 Display할 것이다. 

그런데 사용자는 Delete key를 통해 ListView에 있는 이미지를 삭제하고, 실제 경로에 있는 파일까지 삭제한다고 하면 아래와 같은 예외가 튀어나올 것이다.

파일은 다른 프로세스에서 사용 중이므로 프로세스에서 액세스할 수 없습니다

원인은 무엇일까?

원인은 파일이 다른 프로세스에서 사용 중일 때 파일을 삭제하려면, 먼저 해당 파일을 사용 중인 프로세스에서 파일의 액세스를 해제해야 한다.. 파일 핸들을 정리하고 파일을 닫아야 삭제할 수 있다.

 

그렇다면 우리는 string 형태로 바인딩하여 자동으로 Image의 경로에서 할당하는데 엑세스를 해제할 수가 없다.

이에 대한 해법은 Converter를 이용하여 Image를 할당 한 후, 엑세스 해제하는 방법이 있다.

 

public class ImageLoaderConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        string imagePath = value as string;

        if (string.IsNullOrEmpty(imagePath) || !File.Exists(imagePath))
        {
            return null;
        }

        BitmapImage image = new BitmapImage();

        using (var stream = new FileStream(imagePath, FileMode.Open, FileAccess.Read))
        {
            image.BeginInit();
            image.CacheOption = BitmapCacheOption.OnLoad;
            image.StreamSource = stream;
            image.EndInit();
        }

        image.Freeze(); // 이미지가 스레드에서 안전하게 사용되도록 함
        return image;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}
<Window ...
    xmlns:local="clr-namespace:YourNamespace"
    ...>
    <Window.Resources>
        <local:ImageLoaderConverter x:Key="ImageLoaderConverter" />
    </Window.Resources>
    <Grid>
        <Image x:Name="img" Source="{Binding ImagePath, Converter={StaticResource ImageLoaderConverter}}" />
        <!-- 나머지 UI 요소 -->
    </Grid>
</Window>

자 이런식으로 하면 실제 파일에 대한 액세스는 해제하게 되어 삭제 할때 문제가 없게된다.

 

반응형