Activiz에서는 WPF의 자체 render control을 지원하지 않기 때문에 winform host 를 이용하여 render control을 주입하는 방식으로 사용하게 됩니다.
Winform host를 이용하여 Render control을 생성하고 rendering 하는 것은 쉽습니다.
하지만, 여기에서 주의할 것은 만약에 render control을 갖는 control이 modaless 로 동작하는 경우에는 memory leak을 주의해야 합니다.
WPF control을 종료할 때에 메모리 해제를 직접하지 않을 경우에는 해당 render control 이 처리하고 있는 데이터에 대한 메모리가 release 되지 않고 계속 쌓이게 됩니다.
이게 만약 여러번 modaless 로 사용되었을 경우에는 어플리케이션 메모리가 급증 할 수 있습니다.
이에 대한 해결하기 방법은 매우 간단합니다.
Control 의 unloaded 이벤트에서 winform host 를 dispose 하고 GC.Collect 를 수행하도록 합니다.
이때 Modaless 로 동적으로 생성되는 control 인지 확인하고 winform host를 dispose 할 지를 결정하면 의도치 않게 다른곳에서 static으로 사용되는 디자인에서 control이 없어지지 않도록 예외처리 할 수 있습니다.
<디자인 .xaml >
<sc:SimImageControl x:Class="SimulatorApp.Control.SimImageView"
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:sc="clr-namespace:SimulatorApp.Control"
xmlns:vtk="clr-namespace:Kitware.VTK;assembly=Kitware.VTK"
mc:Ignorable="d"
d:DesignHeight="450" d:DesignWidth="450"
Unloaded="SimImageControl_Unloaded" >
<Grid>
<WindowsFormsHost x:Name="winformHost" Margin="5">
<vtk:RenderWindowControl x:Name="_renderControl" Load="_renderControl_OnLoad" />
</WindowsFormsHost>
</Grid>
</sc:SimImageControl>
<Behind xaml.cs >
private void SimImageControl_Unloaded(object sender, RoutedEventArgs e)
{
if(IsModallessControl)
{
// Must Call winformhost & GC.collect
winformHost.Dispose();
GC.Collect();
}
}
추가적으로 winform host를 dispose 할 때에는 내부에서 관리하는 RenderWindow, Renderer, RenderWindowInteractor 에 대한 메모리를 직접 해지하지 않고 winform host만 dispose 해야 합니다.
만약에 아래와 같이 해지를 하게 되면 AccessViolation 에러가 발생합니다.
_renderControl.RenderWindow.dispose();
winformhost.dispose(); // Error : AccessViolation