# Getting Started with CVB.Net

**URL:** <https://forum.commonvisionblox.com/t/getting-started-with-cvb-net/246>\
**Category:** .Net API\
**Tags:** csharp, tutorial\
**Created:** [September 9, 2019, 10:00pm UTC](https://forum.commonvisionblox.com/t/getting-started-with-cvb-net/246 "2019-09-09T22:00:00Z")\
**Posts on this page:** 1\
**Showing post:** 11

<div class="post-metadata">

**Author:** ![parsd](https://yyz1.discourse-cdn.com/flex027/user_avatar/forum.commonvisionblox.com/parsd/32/7_2.png) [@parsd](https://forum.commonvisionblox.com/u/parsd)\
**Post date:** [September 11, 2019, 11:54am UTC](https://forum.commonvisionblox.com/t/getting-started-with-cvb-net/246/11 "2019-09-11T11:54:42Z")

</div>

# Display a Stream (WPF)

We do a non-MVVM demo of a WPF app for :cvb:. You can create a MVVM app as our controls support binding (see my answer [here](https://forum.commonvisionblox.com/t/async-saving-of-images/573/2) for an example). Let’s create a new _WPF App_ (_Visual C#_) and call it _CvbWpfViewer_:

 ![grafik](https://canada1.discourse-cdn.com/flex027/uploads/commonvisionblox/original/1X/7e3417de9d687a764c93dc28ee653cfd93320e96.png)

After the wizard finishes you should see an empty _MainWindow.xaml_.

> Don’t forget to disable the _Prefer 32-bit_ check-box.

For this app we need the _Stemmer.Cvb.dll_, _Stemmer.Cvb.Wpf.dll_, and _Stemmer.Cvb.Extensions.dll_ as references. To be able to use our :cvb: UI controls, we need to add our namespace to the `<Window ...>`:

> `xmlns:cvb="http://www.commonvisionblox.com/wpf"`

## UI Design

First we add to rows to the grid:

```auto
<Grid.RowDefinitions>
  <RowDefinition Height="*" />
  <RowDefinition Height="Auto" />
</Grid.RowDefinitions>

```

The first row is for the `Display` and the second row for the controls. Let’s add them:

```auto
<cvb:Display x:Name="display" Grid.Row="0" />

<StackPanel Grid.Row="1"
            Orientation="Horizontal" Margin="0,4,0,0">
  <Button x:Name="openButton" Content="Open..." 
          MinWidth="75" Margin="0, 0, 4, 0" />
  <CheckBox x:Name="grabCheckBox" Content="Grab"
            VerticalAlignment="Center" />
</StackPanel>

```

I also gave the `Grid` a `Margin="8"`. Yes, this is just for quickness sake. In a real app you should put the visual stuff in `<Style>`s.

## Adding Behavior

We click on the `Button` and open the events in the _Properties_:

 ![grafik](https://canada1.discourse-cdn.com/flex027/uploads/commonvisionblox/original/1X/9eb2b7040eb519b2deebd5c7b5ff0c897e8c2dc7.png)

Double-click in the text box right to the _Click_ event to create the event handler. Enter the following code:

```auto
private void openButton_Click(object sender, RoutedEventArgs e)
{
  try
  {
    Device device = FileDialogs.LoadByDialog(path => DeviceFactory.Open(path), "CVB Devices|*.vin;*.emu;*.avi");
    if (device == null)
      return; // canceled

    Device = device;
  }
  catch (IOException ex)
  {
    MessageBox.Show(ex.Message, "Error loading device", MessageBoxButton.OK, MessageBoxImage.Error);
  }
}

```

and

```auto
private Device Device
{
  get { return _device; }
  set
  {
    if (!ReferenceEquals(value, _device))
    {
      display.Image = value?.DeviceImage;

      _device?.Dispose(); // old one is not needed anymore
      _device = value;
    }
  }
}
private Device _device;

```

To make this compile add the following namespaces:

```auto
using Stemmer.Cvb;
using Stemmer.Cvb.Wpf;
using System.IO;

```

We use the helper `FileDialogs.LoadByDialog` to easily open a `FileDialog` that returns the opened `Device` or `null` if canceled. This dialog supports _avi_- and _emu_-files as well as preconfigured _vin_-drivers.

We also utilize a `Device MainWindow.Device` property to manage life-time of prior loaded devices and to assign the `DeviceImage` to the `display`. (If `?.` looks unfamiliar: that is automatic `null` handling: `null` is assigned if `value == null`.)

When we run the app and load e.g. the _GenICam.vin_, we see a black image in the `Display`. This is normal as we don’t do “Auto Snap” and no data has been acquired, yet.

Finally we connect the `grabCheckBox`’s _Checked_ and _Unchecked_ events by double-clicking in the text-boxes right from them. We add the following code:

```auto
private async void grabCheckBox_Checked(object sender, RoutedEventArgs e)
{
  Device.Stream.Start();
  openButton.IsEnabled = false;
  try
  {
    while (grabCheckBox.IsChecked ?? false)
    {
      using (StreamImage image = await Device.Stream.WaitAsync())
      {
        // processing
      }
    }
  }
  catch (OperationCanceledException)
  {
    // acquisition was aborted
  }
  finally
  {
    openButton.IsEnabled = true;
  }
}

```

(note the `async` in the event handler’s signature)  
and

```auto
private void grabCheckBox_Unchecked(object sender, RoutedEventArgs e)
{
  if (Device != null && Device.Stream.IsRunning)
    Device.Stream.Abort();
}

```

For this code to compile you need these namespaces:

```auto
using Stemmer.Cvb.Async;
using Stemmer.Cvb.Driver;

```

Ok, this is a lot. But let me point you to the previous post as this is nearly the same except the adjustments for _WPF_:

> [@parsd](#):
>
> ## Stemmer.Cvb.Async Acquisition

## Exit Handling

As described in the previous post, exit handling is important. Sadly _WPF_ _Windows_ are not derived from `IDisposable`. As we store `IDisposable` types (the `Device`) we better implement that interface. But this doesn’t help us here as nobody calls `.Dispose()` on our `MainWindow`. The correct solution would be to implement the `IDisposable` interface and `.Abort()` the acquisition in the `Window`’s _Closing_ event. For briefness sake I put the exit handling directly into the event handler (go back to the designer, select the `Window` and double-click in the text-box right to the _Closing_ event):

```auto
private void Window_Closing(object sender, CancelEventArgs e)
{
  grabCheckBox.IsChecked = false;
  Device?.Dispose();
}

```

(We use the _Closing_ event because at this point in time the `MainWindow` is still alive.)

> **This is how the correct way looks like**
>
> The _Closing_ event has also to be registered and the `MainWindow` must implement `IDisposable`:
> 
> > `public partial class MainWindow : Window, IDisposable`
> 
> Then we need a finalizer:
> 
> ```auto
> ~MainWindow()
> {
> Dispose(false);
> }
> 
> ```
> 
> , the `.Dispose()` method:
> 
> ```auto
> public void Dispose()
> {
> Dispose(true);
> GC.SuppressFinalize(this);
> }
> 
> ```
> 
> , the actual dispose handler:
> 
> ```auto
> protected virtual void Dispose(bool disposing)
> {
> if (disposing)
> {
> Device?.Dispose();
> }
> }
> 
> ```
> 
> , and last but not least our _Closing_ event handler:
> 
> ```auto
> private void Window_Closing(object sender, CancelEventArgs e)
> {
> grabCheckBox.IsChecked = false;
> }
> 
> ```
> 
> In this case we defer clean-up to the user of our `MainWindow`. If it is opened manually, the implementer is responsible for disposing it. In case the framework opens the `MainWindow`, the process is exited anyways and the garbage collector will clean-up the `Device`.

---

_[View the full topic](https://forum.commonvisionblox.com/t/getting-started-with-cvb-net/246)._
