WPF - System.NullReferenceException

Questions, comments and suggestions concerning VintaSoft Imaging .NET SDK.

Moderator: Alex

Post Reply
sebascomeau
Posts: 16
Joined: Fri Jan 31, 2014 5:31 pm

WPF - System.NullReferenceException

Post by sebascomeau »

Hi,

We recently switch from Win32 to WPF for the UI of our application and we get a System.NullReferenceException in our error log. Check the stack trace of the exception.

Code: Select all

System.NullReferenceException: La référence d'objet n'est pas définie à une instance d'un objet.
   à ..SetScrollBarsPosition(Boolean needInvalidate)
   à Vintasoft.Imaging.UI.ImageViewer.ClearImage(Boolean invalidateViewer)
   à Vintasoft.Imaging.UI.ImageViewerController.ProcessNextTask()
   à Vintasoft.Imaging.UI.ImageViewerController.TasksThread()
   à System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   à System.Threading.ThreadHelper.ThreadStart()
Can you help us to figure out the source of this problem?

Thanks,
Sébastien Comeau
Alex
Site Admin
Posts: 2305
Joined: Thu Jul 10, 2008 2:21 pm

Re: WPF - System.NullReferenceException

Post by Alex »

Hi Sébastien,

We need reproduce the issue. Could you provide us a working project which demonstrates the problem? If yes, please send your project to support@vintasoft.com.

Best regards, Alexander
sebascomeau
Posts: 16
Joined: Fri Jan 31, 2014 5:31 pm

Re: WPF - System.NullReferenceException

Post by sebascomeau »

I tried to reproduced this error but no success. I contacted a user that received this error and let her know to send me more information when she will reveives an error. Maybe I will have all the details to reproduce it.
sebascomeau
Posts: 16
Joined: Fri Jan 31, 2014 5:31 pm

Re: WPF - System.NullReferenceException

Post by sebascomeau »

I updated VintaSoft Imaging .NET SDK to the latest version 8.2.8.1 and I received this error stack...

Code: Select all

System.NullReferenceException: La référence d'objet n'est pas définie à une instance d'un objet.
   à ..SetScrollBarsPosition(Boolean needInvalidate)
   à Vintasoft.Imaging.UI.ImageViewer.4(Boolean )
   à ..()
   à ..13()
   à System.Threading.ThreadHelper.ThreadStart_Context(Object state)
   à System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state, Boolean preserveSyncCtx)
   à System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)
   à System.Threading.ThreadHelper.ThreadStart()
We are using the WpfThumbnailViewer and WpfImageViewer in a TabItem. We can load a maximum of 5 TabItem in ou TabControl.

Here`s the code of our TabItem. The image data is loaded from the database in Tiff format.

XAML

Code: Select all

<TabItem x:Class="Dijito.FrontEnd.Controls.Views.DocumentTabItem"
    xmlns:dijitoViews="clr-namespace:Dijito.FrontEnd.Controls.Views"
    xmlns:converters="clr-namespace:Dijito.FrontEnd.Converter"    
    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:vsui="clr-namespace:Vintasoft.Imaging.Wpf.UI;assembly=Vintasoft.Imaging.Wpf.UI"
    mc:Ignorable="d" 
    d:DesignHeight="300" d:DesignWidth="300" >

    <TabItem.Resources>
        <converters:CurrencyConverter x:Key="CurrencyConverter" />
    </TabItem.Resources>
    
    <Grid Margin="-4">
        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="1*"/>
            <ColumnDefinition Width="1*"/>
        </Grid.ColumnDefinitions>

        <ScrollViewer Padding="4" Margin="0 0 4 0">
            <DockPanel Grid.Column="0" Margin="0 0 10 0">
                <!--Informations-->
                <Grid DockPanel.Dock="Top">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="1*"></ColumnDefinition>
                        <ColumnDefinition Width="1*"></ColumnDefinition>
                    </Grid.ColumnDefinitions>
                    <StackPanel>
                        <Label Name="lblCode" Style="{StaticResource FormLabel}" DockPanel.Dock="Top" />
                        <TextBlock Name="tbDocumentCode" Margin="5 0 0 0" />
                    </StackPanel>
                    <StackPanel Grid.Column="1">
                        <Label Name="lblFiscalYear" Style="{StaticResource FormLabel}" DockPanel.Dock="Top" />
                        <TextBlock Name="tbFiscalYear" Margin="5 0 0 0" />
                    </StackPanel>
                </Grid>
                

                <Label Name="lblInformations" Style="{StaticResource FormLabel}" Margin="0 15 0 0" DockPanel.Dock="Top" />
                <DataGrid Name="dgInformations" DockPanel.Dock="Top" ColumnWidth="auto" AutoGenerateColumns="False" IsReadOnly="True" HeadersVisibility="Column" Visibility="Visible" Height="250">
                    <DataGrid.Columns>
                        <DataGridTextColumn x:Name="dgInformationsColumnDate" Binding="{Binding Date}" Width="75"></DataGridTextColumn>
                        <DataGridTextColumn x:Name="dgInformationsColumnDescription" Binding="{Binding Description}" Width="*"></DataGridTextColumn>
                        <DataGridTemplateColumn x:Name="dgInformationsColumnAmount" SortMemberPath="Amount" Width="100">
                            <DataGridTemplateColumn.CellTemplate>
                                <DataTemplate>
                                    <TextBlock Text="{Binding Amount, Converter={StaticResource CurrencyConverter}}" HorizontalAlignment="Right" Margin="2, 0" />
                                </DataTemplate>
                            </DataGridTemplateColumn.CellTemplate>
                        </DataGridTemplateColumn>
                        <DataGridTextColumn x:Name="*" Binding="{Binding *}" Width="40"></DataGridTextColumn>
                        <DataGridTextColumn x:Name="dgInformationsColumnOrganization" Binding="{Binding Organization}" Width="50"></DataGridTextColumn>
                        <DataGridTextColumn x:Name="dgInformationsColumnProgram" Binding="{Binding Program}" Width="50"></DataGridTextColumn>
                        <DataGridTextColumn x:Name="dgInformationsColumnAccount" Binding="{Binding Account}" Width="50"></DataGridTextColumn>
                        <DataGridTextColumn x:Name="dgInformationsColumnTask" Binding="{Binding Task}" Width="50"></DataGridTextColumn>
                        <DataGridTextColumn x:Name="dgInformationsColumnOption" Binding="{Binding Option}" Width="50"></DataGridTextColumn>
                        <DataGridTextColumn x:Name="dgInformationsColumnActivty" Binding="{Binding Activity}" Width="60"></DataGridTextColumn>
                    </DataGrid.Columns>
                </DataGrid>

                <Label Name="lblNotes" Style="{StaticResource FormLabel}" Margin="0 15 0 0" DockPanel.Dock="Top" />
                <Separator Style="{StaticResource {x:Static ToolBar.SeparatorStyleKey}}" DockPanel.Dock="Top" />
                <ScrollViewer VerticalScrollBarVisibility="Auto">
                    <ItemsControl Name="icNotes">
                        <ItemsControl.ItemTemplate>
                            <DataTemplate>
                                <Border BorderBrush="#F2E100" BorderThickness="1,1,1,1" CornerRadius="4,4,4,4" Padding="10" Margin="5" Background="#FFFBC4">
                                    <StackPanel>
                                        <DockPanel Margin="0 0 0 10">
                                            <Border BorderBrush="black" BorderThickness="1" DockPanel.Dock="Left">
                                                <Image Source="{Binding PictureUrl}" VerticalAlignment="Bottom" />
                                            </Border>
                                            <Label DockPanel.Dock="Left" Content="{Binding UserName}" VerticalAlignment="Bottom" Margin="5 0 0 0" Padding="0" FontWeight="Black"  />
                                            <Image DockPanel.Dock="Left" Source="/img/icons/16/time.png" VerticalAlignment="Bottom"  />
                                            <Label DockPanel.Dock="Left" Content="{Binding CreatedOn}" VerticalAlignment="Bottom" Padding="0" FontSize="10"   />
                                            <Button DockPanel.Dock="Right" HorizontalAlignment="Right" Style="{StaticResource FlatButtonStyle}" Name="btnDeleteNote" Click="btnDeleteNote_Click" Visibility="{Binding Visibility}">
                                                <Image Source="/img/icons/16/remove.png" />
                                            </Button>
                                        </DockPanel>
                                        <TextBlock Text="{Binding Content}" TextWrapping="Wrap" />
                                    </StackPanel>
                                </Border>
                            </DataTemplate>
                        </ItemsControl.ItemTemplate>
                        <ItemsControl.ItemsPanel>
                            <ItemsPanelTemplate>
                                <StackPanel Orientation="Vertical"/>
                            </ItemsPanelTemplate>
                        </ItemsControl.ItemsPanel>
                    </ItemsControl>
                </ScrollViewer>
            </DockPanel>
        </ScrollViewer>

        <GridSplitter Width="4" HorizontalAlignment="Right" VerticalAlignment="Stretch" Background="DarkGray" />        

        <DockPanel Grid.Column="1">
            <DockPanel.Background>
                <LinearGradientBrush EndPoint="0,1">
                    <GradientStop Color="#FFDADADA" Offset="0" />
                    <GradientStop Color="#FFC7C7C7" Offset="0.9" />
                    <GradientStop Color="#FFDADADA" Offset="0.98" />
                    <GradientStop Color="DarkGray" Offset="1" />

                </LinearGradientBrush>
            </DockPanel.Background>
            <!--Pages-->
            <ToolBarTray DockPanel.Dock="Top">
                <ToolBar>
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerFirst" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/angle-double-left.png" />
                    </Button>
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerPrev" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/angle-left.png" />
                    </Button>
                    <TextBox Name="txtSelectedPageIndex" Width="40" MaxLength="8" KeyDown="txtSelectedPageIndex_KeyDown" TextAlignment="Center" />
                    <Label Content="/" />
                    <Label Name="lblPageCount" Content="0" />
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerNext" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/angle-right.png" />
                    </Button>
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerLast" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/angle-double-right.png" />
                    </Button>
                    <Separator Margin="10 0 10 0" />
                    <ToggleButton Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerZoomSelection" Checked="btnImageViewerToggleButton_Checked" Unchecked="btnImageViewerToggleButton_Unchecked">
                        <StackPanel Orientation="Horizontal">
                            <Image Source="/img/icons/16/search-square.png" />
                        </StackPanel>
                    </ToggleButton>
                    <ToggleButton Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerZoomScroll" Checked="btnImageViewerToggleButton_Checked" Unchecked="btnImageViewerToggleButton_Unchecked">
                        <StackPanel Orientation="Horizontal">
                            <Image Source="/img/icons/16/search.png" />
                        </StackPanel>
                    </ToggleButton>
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerZoomIn" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/zoom-in.png" />
                    </Button>
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerZoomOut" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/zoom-out.png" />
                    </Button>
                    <ToggleButton Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerPan" Checked="btnImageViewerToggleButton_Checked" Unchecked="btnImageViewerToggleButton_Unchecked">
                        <Image Source="/img/icons/16/move.png" />
                    </ToggleButton>
                    <Separator Margin="10 0 10 0" />
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerRotateLeft" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/rotate-left.png" />
                    </Button>
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerRotateRight" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/rotate-right.png" />
                    </Button>
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerContrastBrightness" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/adjust.png" />
                    </Button>
                    <Separator Margin="10 0 10 0" />

                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerSave" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/save.png" />
                    </Button>
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerDownload" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/download-alt.png" />
                    </Button>
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerPrint" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/print.png" />
                    </Button>
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerDelete" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/trash.png" />
                    </Button>
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerRevert" Click="ImageViewerButton_Click">
                        <StackPanel Orientation="Horizontal">
                            <Image Source="/img/icons/16/mail-reply-all.png" />
                        </StackPanel>
                    </Button>
                    <Separator Margin="10 0 10 0" />
                    <Button Style="{StaticResource ResourceKey=ImageViewerButton}" Name="btnImageViewerInfo" Click="ImageViewerButton_Click">
                        <Image Source="/img/icons/16/info-sign.png" />
                    </Button>
                </ToolBar>
            </ToolBarTray>           

            <vsui:WpfThumbnailViewer Name="wpfThumbnailViewer" 
                                     DockPanel.Dock="Top" 
                                     Height="90" 
                                     MultiSelect="False" 
                                     GenerateOnlyVisibleThumbnails="True"
                                     ThumbnailSize="64,64"
                                     ThumbnailFlowStyle="SingleRow"
                                     AllowDrag="False"
                                     AllowDrop="False"
            ></vsui:WpfThumbnailViewer>
            
            <vsui:WpfImageViewer Name="wpfImageViewer" 
                                 Width="Auto" 
                                 Height="Auto" 
                                 SizeMode="BestFit">
                <vsui:WpfImageViewer.Background>
                    <ImageBrush ImageSource="/img/editor-bg.png" TileMode="Tile" ViewportUnits="Absolute" Viewport="0,0,16,16"></ImageBrush>
                </vsui:WpfImageViewer.Background>
            </vsui:WpfImageViewer>
            
        </DockPanel>
    </Grid>
</TabItem>
Code-behind

Code: Select all

using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using Vintasoft.Imaging;
using Vintasoft.Imaging.ImageProcessing;
using Vintasoft.Imaging.ImageProcessing.Color;
using Vintasoft.Imaging.ImageProcessing.Transforms;
using System.Drawing;
using Microsoft.Win32;
using Dijito.FrontEnd.Helper;
using System.Reflection;
using System.Xml.Linq;
using System.Collections;
using WebSupergoo.ABCpdf8;
using Vintasoft.Imaging.Wpf.UI;
using Vintasoft.Imaging.UI;
using Vintasoft.Imaging.Wpf.UI.VisualTools;

namespace Dijito.FrontEnd.Controls.Views
{
    /// <summary>
    /// Interaction logic for DocumentTabItem.xaml
    /// </summary>
    public partial class DocumentTabItem : TabItem
    {
        private List<int> _zoomValues = new List<int> { 1, 5, 10, 25, 50, 75, 100, 125, 150, 200, 400, 600, 800, 1000 };

        private StatusBarHelper StatusBarHelper
        {
            get
            {
                return Application.Current.Windows.OfType<MainWindow>().SingleOrDefault(x => x.IsActive).StatusBarHelper;
            }
        }

        /// <summary>
        /// Keys are Page IDs, Values are FileData IDs. Should be synchronized with the VintasoftThumbnailViewer image list.
        /// </summary>
        public Dictionary<Guid, Guid> PageData = new Dictionary<Guid, Guid>();

        /// <summary>
        /// Document that is loaded.
        /// </summary>
        public Core.Model.Document Document { get; private set; }
        private Guid _documentId;
        
        public bool HasPages
        {
            get
            {
                return wpfImageViewer.Images.Count > 0;
            }
        }
        
        /// <summary>
        /// Constructor
        /// </summary>
        /// <param name="documentId"></param>
        public DocumentTabItem(Guid documentId)
        {
            this.Loaded += DocumentTabItem_Loaded;
            this.Unloaded += DocumentTabItem_Unloaded;
            
            InitializeComponent();

            _documentId = documentId;

            wpfImageViewer.ImageLoaded += wpfImageViewer_ImageLoaded;
            wpfImageViewer.KeyDown += wpfImageViewer_KeyDown;

            wpfThumbnailViewer.MasterViewer = wpfImageViewer;
            wpfThumbnailViewer.KeyDown += wpfThumbnailViewer_KeyDown;
            wpfThumbnailViewer.FocusedIndexChanged += wpfThumbnailViewer_FocusedIndexChanged;

            //Default tool item
            btnImageViewerZoomScroll.IsChecked = true;
        }
        
        private void DocumentTabItem_Loaded(object sender, RoutedEventArgs e)
        {
            SetText();
            RefreshUI();
        }

        private void DocumentTabItem_Unloaded(object sender, RoutedEventArgs e)
        {
            System.Diagnostics.Debug.WriteLine(string.Format("Unload: {0}", _documentId));

            // unsubcribed events
            wpfImageViewer.ImageLoaded -= wpfImageViewer_ImageLoaded;
            wpfImageViewer.KeyDown -= wpfImageViewer_KeyDown;

            wpfThumbnailViewer.KeyDown -= wpfThumbnailViewer_KeyDown;
            wpfThumbnailViewer.FocusedIndexChanged -= wpfThumbnailViewer_FocusedIndexChanged;
            
            wpfImageViewer.Images.ClearAndDisposeItems();
            wpfThumbnailViewer.Images.ClearAndDisposeItems();
            
            wpfImageViewer.Dispose();
            wpfImageViewer = null;
            
            wpfThumbnailViewer.Dispose();
            wpfThumbnailViewer = null;

            dgInformations.ItemsSource = null;
            icNotes.ItemsSource = null;
            this.Header = null;
        }

        /// <summary>
        /// Gets the Page ID for the currently selected image
        /// </summary>
        /// <returns></returns>
        public Guid? GetSelectedPageId()
        {
            Guid? result = (Guid?)null;

            if (PageData != null)
            {
                List<KeyValuePair<Guid, Guid>> list = PageData.ToList();

                if (wpfThumbnailViewer.FocusedIndex < list.Count)
                {
                    return list[wpfThumbnailViewer.FocusedIndex].Key;
                }
            }
            return (Guid?)null;
        }

        /// <summary>
        /// Sets static texts (labels etc.)
        /// </summary>
        private void SetText()
        {
            dgInformationsColumnDate.Header = FrontEnd.Resources.Localization.Information_Field_Date;
            dgInformationsColumnDescription.Header = FrontEnd.Resources.Localization.Information_Field_Description;
            dgInformationsColumnAmount.Header = FrontEnd.Resources.Localization.Information_Field_Amount;
            *.Header = Core.Model.FinancialCodeType.GetAbbreviation(Core.Enumeration.FinancialCodeType.*);
            dgInformationsColumnOrganization.Header = Core.Model.FinancialCodeType.GetAbbreviation(Core.Enumeration.FinancialCodeType.Organization);
            dgInformationsColumnProgram.Header = Core.Model.FinancialCodeType.GetAbbreviation(Core.Enumeration.FinancialCodeType.Program);
            dgInformationsColumnAccount.Header = Core.Model.FinancialCodeType.GetAbbreviation(Core.Enumeration.FinancialCodeType.Account);
            dgInformationsColumnTask.Header = Core.Model.FinancialCodeType.GetAbbreviation(Core.Enumeration.FinancialCodeType.Task);
            dgInformationsColumnOption.Header = Core.Model.FinancialCodeType.GetAbbreviation(Core.Enumeration.FinancialCodeType.Option);
            dgInformationsColumnActivty.Header = Core.Model.FinancialCodeType.GetAbbreviation(Core.Enumeration.FinancialCodeType.Activity);

            btnImageViewerFirst.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_FirstPage;
            btnImageViewerPrev.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_PrevPage;
            btnImageViewerNext.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_NextPage;
            btnImageViewerLast.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_LastPage;
            btnImageViewerZoomSelection.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_ZoomSelection;
            btnImageViewerZoomScroll.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_ScrollZoom;
            btnImageViewerZoomIn.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_ZoomIn;
            btnImageViewerZoomOut.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_ZoomOut;
            btnImageViewerPan.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_Pan;
            btnImageViewerRotateLeft.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_RotateCounterClockwork;
            btnImageViewerRotateRight.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_RotateClockwork;
            btnImageViewerContrastBrightness.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_ContrastBrightness;
            btnImageViewerSave.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_SavePage;
            btnImageViewerDownload.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_DownloadPage;
            btnImageViewerPrint.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_PrintPages;
            btnImageViewerDelete.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_DeletePage;
            btnImageViewerRevert.ToolTip = FrontEnd.Resources.Localization.DocumentEditor_Tooltip_RevertPageToOriginal;
            btnImageViewerInfo.ToolTip = FrontEnd.Resources.Localization.Dialog_PageInfo_Tooltip;

            lblCode.Content = FrontEnd.Resources.Localization.Document_Field_Code;
            lblFiscalYear.Content = FrontEnd.Resources.Localization.Document_Field_FiscalYear;
            lblInformations.Content = FrontEnd.Resources.Localization.Informations;
            lblNotes.Content = FrontEnd.Resources.Localization.Notes;
        }

        /// <summary>
        /// Refetch data from database, update all dynamic UI elements
        /// </summary>
        public void RefreshUI()
        {
            using (Core.Logic.DijitoLogic logic = ApplicationHelper.GetLogic())
            {
                // document info
                Document = logic.Document.Get(_documentId);

                // set TabItem header
                this.Header = new ContentControl
                {
                    Content = Document.ToString(),
                    ContextMenu = BuildContextMenu()
                };

                tbDocumentCode.Text = Document.Code;
                tbFiscalYear.Text = Document.DisplayFiscalYear;

                RefreshInformations(logic);
                RefreshNotes(logic);
                RefreshPages();
            }
        }

        private ContextMenu BuildContextMenu()
        {
            ContextMenu cm = new ContextMenu();

            // add close menu item
            MenuItem miClose = new MenuItem();
            miClose.Header = FrontEnd.Resources.Localization.DocumentTab_Close;
            miClose.CommandParameter = "CLOSE";
            miClose.Icon = new System.Windows.Controls.Image { Source = new BitmapImage(new Uri("/img/icons/16/remove.png", UriKind.Relative)) };
            miClose.Click += contextMenuItem_Click;

            // add close all menu item
            MenuItem miCloseAll = new MenuItem();
            miCloseAll.Header = FrontEnd.Resources.Localization.DocumentTab_CloseAll;
            miCloseAll.CommandParameter = "CLOSEALL";
            miCloseAll.Icon = new System.Windows.Controls.Image { Source = new BitmapImage(new Uri("/img/icons/16/remove.png", UriKind.Relative)) };
            miCloseAll.Click += contextMenuItem_Click;

            // add close all BUT this menu item
            MenuItem miCloseAllButThis = new MenuItem();
            miCloseAllButThis.Header = FrontEnd.Resources.Localization.DocumentTab_CloseAllButThis;
            miCloseAllButThis.CommandParameter = "CLOSEALLBUTTHIS";
            miCloseAllButThis.Icon = new System.Windows.Controls.Image { Source = new BitmapImage(new Uri("/img/icons/16/remove.png", UriKind.Relative)) };
            miCloseAllButThis.Click += contextMenuItem_Click;

            cm.Items.Add(miClose);
            cm.Items.Add(miCloseAll);
            cm.Items.Add(miCloseAllButThis);

            return cm;
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="logic"></param>
        public void RefreshInformations(Core.Logic.DijitoLogic logic)
        {
            dgInformations.ItemsSource = logic.Information.GetList(Document.DocumentId).Select(i => new ViewModel.DocumentInformationGridItem(i)).ToList();
        }

        public void RefreshNotes(Core.Logic.DijitoLogic logic)
        {
            icNotes.ItemsSource = logic.Note.GetList(Document.DocumentId).Select(n => new ViewModel.DocumentNoteGridItem(n)).ToList();
        }

        /// <summary>
        /// 
        /// </summary>
        /// <param name="selectedPageIndex">Index is zero based</param>
        public void RefreshPages(int selectedPageIndex = 0)
        {
            wpfImageViewer.Images.ClearAndDisposeItems();

            using (Core.Logic.DijitoLogic logic = ApplicationHelper.GetLogic())
            {
                PageData = logic.Page.GetList(Document.DocumentId).ToDictionary(p => p.PageId, p => p.FileDataId);

                // load pages by chunk fetching of 10
                int splitSize = 10;

                for(int x = 0; x < PageData.Count; x += splitSize)
                {
                    Dictionary<Guid, Guid> chunk = PageData.Skip(x).Take(splitSize).ToDictionary(c => c.Key, c => c.Value);

                    List<Core.Model.FileData> filesdata = logic.FileData.GetListFromIds(chunk.Select(kvp => kvp.Value).ToList());

                    foreach (KeyValuePair<Guid, Guid> kvp in chunk)
                    {
                        wpfImageViewer.Images.Add(new MemoryStream(filesdata.Single(fd => fd.FileDataId == kvp.Value).Data));
                    }
                }
            }

            if (selectedPageIndex < wpfImageViewer.Images.Count)
            {
                wpfThumbnailViewer.FocusedIndex = selectedPageIndex; // its zero based
            }
            else
            {
                wpfThumbnailViewer.FocusedIndex = -1;
            }

            SetToolbar();
        }

        /// <summary>
        /// 
        /// </summary>
        private void DeleteSelectedPage()
        {
            Guid? selectedPageId = GetSelectedPageId();

            if (selectedPageId.HasValue)
            {
                MessageBoxResult result = MessageBox.Show(FrontEnd.Resources.Localization.ConfirmDeletePage, Core.Model.SystemSettings.ApplicationNameWithExtras, MessageBoxButton.YesNo, MessageBoxImage.Question);

                if (result == MessageBoxResult.Yes)
                {
                    try
                    {
                        using (Core.Logic.DijitoLogic logic = ApplicationHelper.GetLogic())
                        {
                            logic.Page.Delete(selectedPageId.Value);
                        }

                        int imageIndex = wpfThumbnailViewer.FocusedIndex;
                        wpfImageViewer.Images.RemoveAt(imageIndex);
                        PageData.Remove(PageData.ToArray()[imageIndex].Key);
                    }
                    catch (Core.Exception.Document.NotFoundException)
                    {
                        MessageBox.Show(string.Format(FrontEnd.Resources.Localization.DocumentDeletedClosing, Environment.NewLine), Core.Model.SystemSettings.ApplicationNameWithExtras, MessageBoxButton.OK, MessageBoxImage.Information);
                        ((TabControl)this.Parent).Items.Remove(this);
                    }
                    catch (Core.Exception.Page.NotFoundException)
                    {
                        MessageBox.Show(string.Format(FrontEnd.Resources.Localization.PageDeletedRefresh, Environment.NewLine), Core.Model.SystemSettings.ApplicationNameWithExtras, MessageBoxButton.OK, MessageBoxImage.Information);
                        RefreshUI();
                    }
                }
            }

            SetToolbar();
        }

        private void ImageViewerButton_Click(object sender, RoutedEventArgs e)
        {
            if (wpfImageViewer.Image != null)
            {
                if (e.Source == btnImageViewerFirst)
                {
                    if (wpfThumbnailViewer.Images.Count > 0)
                    {
                        wpfThumbnailViewer.FocusedIndex = 0;
                    }
                }
                if (e.Source == btnImageViewerPrev)
                {
                    if (wpfThumbnailViewer.FocusedIndex > 0)
                    {
                        wpfThumbnailViewer.FocusedIndex--;
                    }
                }
                else if (e.Source == btnImageViewerNext)
                {
                    if (wpfThumbnailViewer.FocusedIndex < wpfThumbnailViewer.Images.Count - 1)
                    {
                        wpfThumbnailViewer.FocusedIndex++;
                    }
                }
                else if (e.Source == btnImageViewerLast)
                {
                    if (wpfThumbnailViewer.Images.Count > 0)
                    {
                        wpfThumbnailViewer.FocusedIndex = wpfThumbnailViewer.Images.Count - 1;
                    }
                }
                else if (e.Source == btnImageViewerZoomIn)
                {
                    if (wpfImageViewer.Zoom < _zoomValues.Max())
                    {
                        wpfImageViewer.SizeMode = ImageSizeMode.Zoom;
                        wpfImageViewer.Zoom = _zoomValues.Where(z => z > wpfImageViewer.Zoom).Min();
                    }
                }
                else if (e.Source == btnImageViewerZoomOut)
                {
                    if (wpfImageViewer.Zoom > _zoomValues.Min())
                    {
                        wpfImageViewer.SizeMode = ImageSizeMode.Zoom;
                        wpfImageViewer.Zoom = _zoomValues.Where(z => z < wpfImageViewer.Zoom).Max();
                    }
                }
                else if (e.Source == btnImageViewerRotateLeft || e.Source == btnImageViewerRotateRight)
                {
                    if (!wpfImageViewer.Image.IsProcessing)
                    {
                        int angle = (e.Source == btnImageViewerRotateLeft) ? -90 : 90;
                        (new RotateCommand(angle, BorderColorType.Black)).ExecuteInPlace(wpfImageViewer.Image);
                    }
                }
                else if (e.Source == btnImageViewerSave)
                {
                    StatusBarHelper.SetStatusStart(StatusBarHelper.StatusIcon.Save, FrontEnd.Resources.Localization.Status_SavingPage);

                    Guid? selectedPageId = GetSelectedPageId();

                    if (selectedPageId.HasValue)
                    {
                        MemoryStream stream = new MemoryStream();
                        wpfImageViewer.Image.Save(stream, new Vintasoft.Imaging.Codecs.Encoders.TiffEncoder());

                        try
                        {
                            using (Core.Logic.DijitoLogic logic = ApplicationHelper.GetLogic())
                            {
                                Guid fileDataId;
                                logic.Page.Edit(selectedPageId.Value, stream, out fileDataId);
                                PageData[selectedPageId.Value] = fileDataId;
                            }
                        }
                        catch (Core.Exception.Document.NotFoundException)
                        {
                            MessageBox.Show(string.Format(FrontEnd.Resources.Localization.DocumentDeletedClosing, Environment.NewLine), Core.Model.SystemSettings.ApplicationNameWithExtras, MessageBoxButton.OK, MessageBoxImage.Information);
                            ((TabControl)this.Parent).Items.Remove(this);
                        }
                        catch (Core.Exception.Page.NotFoundException)
                        {
                            MessageBox.Show(string.Format(FrontEnd.Resources.Localization.PageDeletedRefresh, Environment.NewLine), Core.Model.SystemSettings.ApplicationNameWithExtras, MessageBoxButton.OK, MessageBoxImage.Information);
                            RefreshUI();
                        }
                    }
                    StatusBarHelper.SetStatusEnd(StatusBarHelper.StatusIcon.Done, FrontEnd.Resources.Localization.Status_SavingPageDone);
                }
                else if (e.Source == btnImageViewerRevert)
                {
                    Guid? selectedPageId = GetSelectedPageId();

                    if (selectedPageId.HasValue)
                    {
                        MessageBoxResult dialogResult = System.Windows.MessageBox.Show(FrontEnd.Resources.Localization.ConfirmPageRevert, Core.Model.SystemSettings.ApplicationNameWithExtras, MessageBoxButton.YesNo, MessageBoxImage.Question);
                        if (dialogResult == MessageBoxResult.Yes)
                        {
                            try
                            {
                                using (Core.Logic.DijitoLogic logic = ApplicationHelper.GetLogic())
                                {
                                    Guid fileDataId;
                                    logic.Page.Revert(selectedPageId.Value, out fileDataId);

                                    wpfImageViewer.Image.SetImage(new VintasoftImage(new MemoryStream(logic.FileData.GetBytes(fileDataId))));
                                    PageData[selectedPageId.Value] = fileDataId;
                                }
                            }
                            catch (Core.Exception.Document.NotFoundException)
                            {
                                MessageBox.Show(string.Format(FrontEnd.Resources.Localization.DocumentDeletedClosing, Environment.NewLine), Core.Model.SystemSettings.ApplicationNameWithExtras, MessageBoxButton.OK, MessageBoxImage.Information);
                                ((TabControl)this.Parent).Items.Remove(this);
                            }
                            catch (Core.Exception.Page.NotFoundException)
                            {
                                MessageBox.Show(string.Format(FrontEnd.Resources.Localization.PageDeletedRefresh, Environment.NewLine), Core.Model.SystemSettings.ApplicationNameWithExtras, MessageBoxButton.OK, MessageBoxImage.Information);
                                RefreshUI();
                            }
                        }
                    }
                }
                else if (e.Source == btnImageViewerDownload)
                {
                    if (wpfImageViewer.Image != null)
                    {
                        SaveFileDialog saveFileDialog = new SaveFileDialog();
                        saveFileDialog.AddExtension = true;
                        saveFileDialog.FileName = Document.ToString();
                        saveFileDialog.Filter = FrontEnd.Resources.Localization.FileFilter_PDF;
                        saveFileDialog.DefaultExt = ".pdf";

                        if (saveFileDialog.ShowDialog() == true)
                        {
                            try
                            {
                                using (Core.Logic.DijitoLogic logic = ApplicationHelper.GetLogic())
                                {
                                    logic.Page.SavePDF(GetSelectedPageId().Value, saveFileDialog.FileName);
                                }

                                System.Diagnostics.Process.Start(saveFileDialog.FileName);
                            }
                            catch (Core.Exception.Document.NotFoundException)
                            {
                                MessageBox.Show(string.Format(FrontEnd.Resources.Localization.DocumentDeletedClosing, Environment.NewLine), Core.Model.SystemSettings.ApplicationNameWithExtras, MessageBoxButton.OK, MessageBoxImage.Information);
                                ((TabControl)this.Parent).Items.Remove(this);
                            }
                            catch (Core.Exception.Page.NotFoundException)
                            {
                                MessageBox.Show(string.Format(FrontEnd.Resources.Localization.PageDeletedRefresh, Environment.NewLine), Core.Model.SystemSettings.ApplicationNameWithExtras, MessageBoxButton.OK, MessageBoxImage.Information);
                                RefreshUI();
                            }
                            catch (Exception)
                            {
                                System.Windows.MessageBox.Show(FrontEnd.Resources.Localization.FileWriteErrorMessage, Core.Model.SystemSettings.ApplicationNameWithExtras, MessageBoxButton.OK);
                            }
                        }
                    }
                }
                else if (e.Source == btnImageViewerDelete)
                {
                    DeleteSelectedPage();
                }
                else if (e.Source == btnImageViewerPrint)
                {
                    if (wpfImageViewer.Image != null)
                    {
                        using (PrintHelper printHelper = new FrontEnd.Helper.PrintHelper(wpfThumbnailViewer, PageRangeSelection.CurrentPage, Document.ToString()))
                        {
                            printHelper.Print();
                        }
                    }
                }
                else if (e.Source == btnImageViewerContrastBrightness)
                {
                    Dialogs.ContrastBrightness dlg = new Dialogs.ContrastBrightness(wpfImageViewer);
                    dlg.Owner = Window.GetWindow(this);
                    dlg.ShowDialog();
                }
                else if (e.Source == btnImageViewerInfo)
                {
                    Guid? selectedPageId = GetSelectedPageId();

                    if (selectedPageId.HasValue)
                    {
                        Dialogs.PageInfo dlg = new Dialogs.PageInfo(selectedPageId.Value);
                        dlg.Owner = Window.GetWindow(this);
                        dlg.ShowDialog();
                    }
                }
            }
        }

        private void btnImageViewerToggleButton_Checked(object sender, RoutedEventArgs e)
        {
            // reset toggle buttons
            new List<ToggleButton>()
            {
                btnImageViewerZoomSelection,
                btnImageViewerZoomScroll,
                btnImageViewerPan
            }
            .Where(obj => e.Source != obj).ToList()
            .ForEach(obj => obj.IsChecked = false);

            // set current tool
            if (e.Source == btnImageViewerZoomScroll)
            {
                wpfImageViewer.VisualTool = new WpfZoomTool();
            }
            else if (e.Source == btnImageViewerZoomSelection)
            {
                wpfImageViewer.VisualTool = new WpfZoomSelectionTool();
            }
            else if (e.Source == btnImageViewerPan)
            {
                wpfImageViewer.VisualTool = new WpfPanTool();
            }

            // only enable if an image is selected
            wpfImageViewer.VisualTool.Enabled = (wpfImageViewer.Image != null);
        }

        private void btnImageViewerToggleButton_Unchecked(object sender, RoutedEventArgs e)
        {
            wpfImageViewer.VisualTool = null;
        }

        private void btnCloseTab_Click(object sender, RoutedEventArgs e)
        {
            ((TabControl)this.Parent).Items.Remove(this);
        }

        private void wpfImageViewer_ImageLoaded(object sender, ImageLoadedEventArgs e)
        {
            wpfImageViewer.SizeMode = ImageSizeMode.BestFit;

            if (wpfImageViewer.VisualTool != null)
            {
                wpfImageViewer.VisualTool.Enabled = true;
            }
        }

        private void wpfImageViewer_KeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = true;
        }

        private void wpfThumbnailViewer_KeyDown(object sender, KeyEventArgs e)
        {
            e.Handled = true;
        }

        private void wpfThumbnailViewer_FocusedIndexChanged(object sender, PropertyChangedEventArgs<int> e)
        {
            if (Parent != null)
            {
                if (wpfImageViewer.VisualTool != null)
                {
                    wpfImageViewer.VisualTool.Enabled = (e.NewValue > -1);
                }

                // set the selected page index
                txtSelectedPageIndex.Text = (e.NewValue + 1).ToString();
            }
        }

        private void btnDeleteNote_Click(object sender, RoutedEventArgs e)
        {
            Button btn = (Button)sender;

            if (btn.DataContext is ViewModel.DocumentNoteGridItem)
            {

                MessageBoxResult dialogResult = MessageBox.Show(FrontEnd.Resources.Localization.DocumentEditor_DeleteNote_Confirm, Core.Model.SystemSettings.ApplicationNameWithExtras, MessageBoxButton.YesNo, MessageBoxImage.Question);

                if (dialogResult == MessageBoxResult.Yes)
                {
                    ViewModel.DocumentNoteGridItem item = (ViewModel.DocumentNoteGridItem)btn.DataContext;

                    try
                    {
                        using (Core.Logic.DijitoLogic logic = ApplicationHelper.GetLogic())
                        {
                            logic.Note.Delete(item.NoteId);
                            RefreshNotes(logic);
                        }
                    }
                    catch (Core.Exception.BaseForbiddenException)
                    {
                        MessageBox.Show(FrontEnd.Resources.Localization.DocumentEditor_DeleteNoteForbidden, Core.Model.SystemSettings.ApplicationNameWithExtras, MessageBoxButton.OK, MessageBoxImage.Exclamation);
                    }
                }
            }
        }

        public void SetToolbar()
        {
            bool authUserCanManageDocuments = ApplicationHelper.Properties.GetValue<bool>(ApplicationHelper.Properties.Key.AuthenticatedUser_CanManageDocuments);
            bool imageSelected = (wpfThumbnailViewer.FocusedIndex > -1);

            // actions that require rights            
            btnImageViewerSave.IsEnabled = authUserCanManageDocuments && imageSelected;
            btnImageViewerDelete.IsEnabled = authUserCanManageDocuments && imageSelected;
            btnImageViewerRevert.IsEnabled = authUserCanManageDocuments && imageSelected;

            // other buttons
            btnImageViewerFirst.IsEnabled = imageSelected;
            btnImageViewerPrev.IsEnabled = imageSelected;
            txtSelectedPageIndex.Text = imageSelected ? (wpfThumbnailViewer.FocusedIndex + 1).ToString() : "";
            txtSelectedPageIndex.IsEnabled = imageSelected;
            lblPageCount.Content = imageSelected ? wpfThumbnailViewer.Images.Count.ToString() : "0";
            btnImageViewerPrev.IsEnabled = imageSelected;
            btnImageViewerNext.IsEnabled = imageSelected;
            btnImageViewerLast.IsEnabled = imageSelected;
            btnImageViewerZoomScroll.IsEnabled = imageSelected;
            btnImageViewerZoomSelection.IsEnabled = imageSelected;
            btnImageViewerZoomIn.IsEnabled = imageSelected;
            btnImageViewerZoomOut.IsEnabled = imageSelected;
            btnImageViewerPan.IsEnabled = imageSelected;
            btnImageViewerRotateLeft.IsEnabled = imageSelected;
            btnImageViewerRotateRight.IsEnabled = imageSelected;
            btnImageViewerContrastBrightness.IsEnabled = imageSelected;
            btnImageViewerDownload.IsEnabled = imageSelected;
            btnImageViewerPrint.IsEnabled = imageSelected;
            btnImageViewerInfo.IsEnabled = imageSelected;
        }

        private void contextMenuItem_Click(object sender, RoutedEventArgs e)
        {
            TabControl tabControl = (TabControl)this.Parent;

            switch (((MenuItem)sender).CommandParameter.ToString())
            {
                case "CLOSE":

                    tabControl.Items.Remove(this);
                    break;

                case "CLOSEALL":

                    tabControl.Items.Clear();
                    break;

                case "CLOSEALLBUTTHIS":

                    for (int i = tabControl.Items.Count - 1; i >= 0; i--)
                    {
                        TabItem tabItem = (TabItem)tabControl.Items[i];

                        if (tabItem != this)
                        {
                            tabControl.Items.Remove(tabItem);
                        }
                    }

                    break;
            }
        }

        private void txtSelectedPageIndex_KeyDown(object sender, KeyEventArgs e)
        {
            if (e.Key == Key.Enter) // enter
            {
                int value;
                if (int.TryParse(txtSelectedPageIndex.Text, out value) && value > 0 && value <= wpfImageViewer.Images.Count)
                {
                    wpfThumbnailViewer.FocusedIndex = value - 1;
                }
                else
                {
                    txtSelectedPageIndex.Text = (wpfThumbnailViewer.FocusedIndex + 1).ToString();
                }

            }
        }
    }
}
sebascomeau
Posts: 16
Joined: Fri Jan 31, 2014 5:31 pm

Re: WPF - System.NullReferenceException

Post by sebascomeau »

We comment all the lines in the DocumentTabItem_Unloaded event that dispose objects when a TabItem is closing. This was there to free memory and mostly for the Win32 image and thumbnail viewer that was loaded programmatically. I guess we don`t need this anymore with the WPF sdk.

No error was logged in yet.

I will keep you updated.
Sébastien Comeau
Alex
Site Admin
Posts: 2305
Joined: Thu Jul 10, 2008 2:21 pm

Re: WPF - System.NullReferenceException

Post by Alex »

Hi Sébastien,

Thank you for information. We have reproduced and fixed the bug in WPF image viewer. Version with bug fix will be available next week.


About disposing the objects: Calling of the ClearAndDisposeItems method of image collection, associated with viewer, is obligatory. Without calling the method images stored in collection will not be disposed.

In other words, the following code lines are obligatory:

Code: Select all

wpfImageViewer.Images.ClearAndDisposeItems();
wpfThumbnailViewer.Images.ClearAndDisposeItems();
The following code lines are necessary but not obligatory:

Code: Select all

wpfImageViewer.Dispose();
wpfThumbnailViewer.Dispose();
Best regards, Alexander
sebascomeau
Posts: 16
Joined: Fri Jan 31, 2014 5:31 pm

Re: WPF - System.NullReferenceException

Post by sebascomeau »

We will try to clear and dispose images from the image viewer to clear the memory.

Is the fix has been released in version 8.2.10.1?

Thanks,
Sébastien Comeau
Alex
Site Admin
Posts: 2305
Joined: Thu Jul 10, 2008 2:21 pm

Re: WPF - System.NullReferenceException

Post by Alex »

Hi Sébastien,
We will try to clear and dispose images from the image viewer to clear the memory.
Is the fix has been released in version 8.2.10.1?
Yes, problem is fixed since version 8.2.9.1.

Best regards, Alexander
Post Reply