환경 :

Window10, Visual Studio 2019, WPF, MVVMLight, OpencvSharp

 

솔루션 구조

usercontrol 폴더

ImageViewer.xaml 

<UserControl x:Class="WpfApp1.usercontrol.ImageViewer"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:WpfApp1.usercontrol"
             mc:Ignorable="d" 
             d:DesignHeight="450" d:DesignWidth="800">
    <Grid>
        <Image x:Name="image"/>
    </Grid>
</UserControl>

 

ImageViewer.xaml.cs

using OpenCvSharp;
using System.Windows;
using System.Windows.Controls;
using WpfApp1.utility;

namespace WpfApp1.usercontrol
{
    /// <summary>
    /// ImageViewer.xaml에 대한 상호 작용 논리
    /// </summary>
    public partial class ImageViewer : UserControl
    {
        public ImageViewer()
        {
            InitializeComponent();
        }

        public Mat MatImage
        {
            get { return (Mat)GetValue(MyProperty); }
            set { SetValue(MyProperty, value); }
        }

        public static readonly DependencyProperty MyProperty =
            DependencyProperty.Register(
                "MatImage",
                typeof(Mat),
                typeof(ImageViewer),
                new FrameworkPropertyMetadata(new PropertyChangedCallback(OnMyPropertyChanged)));


        private static void OnMyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
        {
            ImageViewer viewer = d as ImageViewer;
            viewer.image.Source = ImageHandler.IplImageToInteropBitmap((e.NewValue as Mat));
        }
    }
}

 

주요코드 

1. MatImage의 GetValue,SetValue

 

2. MyProperty의 등록 과정

DependecyProperty.Register(

"MatImage",                      // 실제 xaml에 노출 시킬 변수 명 추 후 Binding 시킨다.

typeof(Mat),                      // 위의 MatImage의 타입을 정의한다.

typeof(ImageViewer),          //  MatImage 변수를 가지고 있는 객체 타입을 정의한다.

new FrameworkPropertyMetadata(new PropertyChangedCallback(OnMyPropertyChanged)));

//OnMyPropertyChanged 함수로 콜백을 등록한다.

 

3. OnMyPropertyChanged 함수

   DependecyObject - MatImage 인스턴스를 가지고 있는 오너 인스턴스 타입으로 사용.

   DependencyPropertyChangedEventArgs - 외부 Binding을 통해 전달된 Mat Type의 인스턴스.

  

private static void OnMyPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
    ImageViewer viewer = d as ImageViewer; // 오너 인스턴스로 변환
    
    //e.NewValue as Mat으로 외부에서 바인딩한 데이터 변환
    viewer.image.Source = ImageHandler.IplImageToInteropBitmap((e.NewValue as Mat)); 
    
}

   

 

ViewModel 폴더 

MainViewModel.cs

using GalaSoft.MvvmLight;
using GalaSoft.MvvmLight.Command;
using Microsoft.Win32;
using OpenCvSharp;
using WpfApp1.utility;

namespace WpfApp1.ViewModel
{
    /// <summary>
    /// This class contains properties that the main View can data bind to.
    /// <para>
    /// Use the <strong>mvvminpc</strong> snippet to add bindable properties to this ViewModel.
    /// </para>
    /// <para>
    /// You can also use Blend to data bind with the tool's support.
    /// </para>
    /// <para>
    /// See http://www.galasoft.ch/mvvm
    /// </para>
    /// </summary>
    public class MainViewModel : ViewModelBase
    {
        Mat _matImage;
        public Mat matImage
        {
            get
            {
                return _matImage;
            }
            set
            {
                _matImage = value;
                RaisePropertyChanged(() => matImage);
            }
        }

        public RelayCommand OpenImage { get; set; }
        public MainViewModel()
        {
            OpenImage = new RelayCommand(OpenImageAction);
        }

        void OpenImageAction()
        {
            OpenFileDialog openFileDialog = new OpenFileDialog();

            openFileDialog.RestoreDirectory = true;
            openFileDialog.DefaultExt = "jpg";
            openFileDialog.Filter = "Images Files(*.jpg; *.bmp; *.png)|*.jpg;*.bmp;*.png";

            if (openFileDialog.ShowDialog() == true)
            {
                //Get the path of specified file
                string strImagePath = openFileDialog.FileName;
                matImage = ImageHandler.OpenImage(strImagePath);
            }
        }
    }
}

주요 코드

1. matImage 프로퍼티를 이용한 바인딩 코드

Mat _matImage;
public Mat matImage
{
    get
    {
        return _matImage;
    }
    set
    {
        _matImage = value;
        RaisePropertyChanged(() => matImage);
    }
}

 

MainWindow.xaml

<Window x:Class="WpfApp1.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfApp1"
        xmlns:uc="clr-namespace:WpfApp1.usercontrol"
        mc:Ignorable="d"
        DataContext="{Binding Source={StaticResource Locator}, Path=Main}"
        Title="MainWindow" Height="450" Width="800">
    <Grid>
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="*"/>
            <ColumnDefinition Width="*"/>
        </Grid.ColumnDefinitions>
        
        <uc:ImageViewer MatImage="{Binding matImage}" Grid.Column="0"/>
        <Button Command="{Binding OpenImage}" Grid.Column="1"/>
    </Grid>
</Window>

주요코드

ImageViewer에서 등록한 MatImage를 MainViewModel의 matImage 프로퍼티에 바인딩.

<uc:ImageViewer MatImage="{Binding matImage}" Grid.Column="0"/>

 

결과

이미지 로드 전
이미지 로드 다이얼로그 생성
이미지 로드 완료!

+ Recent posts