Thursday, June 13, 2013

InkCanvas in WPF – MVVM – StrokeCollection binding


 
After long time, I got some good quality work in this project. Today I used InkCanvas in WPF-MVVM. Then I saved the shapes or drawing drawn within, to database.
Saving anything to database is OK, but the issues is – how do you get the byte array from InkCanvas Strokes? Een the major issue is how do get Strokes from InkCanvas?
Below article explains InkCanvas binding in WPF – MVVM. Alright then, to start with create a WPF project. Have ViewModel folder added in it; to have logic separation from Views. So final Structure of you application will be as follows –

 

Add InkCanvas in your XAML file and Ellipse in it to have drawing within it as written below –
<Window x:Class="StokesCollectionInMVVM.MainWindow"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <InkCanvas Background="Aqua" Strokes="{Binding StrokesEllipse}">
        <Ellipse Height="100" HorizontalAlignment="Left" Margin="116,100,0,0" Name="ellipse1" Stroke="Black" VerticalAlignment="Top" Width="200" />   
        </InkCanvas>
    </Grid>
</Window>

The view model code will be as follows –
Class variables and View model class definition is as follows –
public class MainWindowsViewModel : INotifyPropertyChanged
    {
        #region INotifyPropertyChanged implementation
        public event PropertyChangedEventHandler PropertyChanged; 

        private void RaisePropertyChanged(string propertyName)
        {
            if (PropertyChanged != null)
            {
                PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
            }
        }
        #endregion 

        #region Class variables       

        private StrokeCollection _strokesEllipse = null;

        #endregion

In constructor – [Note – Code to save byte array in database and retrieve it from database is skipped]
public MainWindowsViewModel()
        {
            //to autopopulate saved drawing on UI -
            //read byte array from say - database and store in EllipseDrawing property
            if (EllipseDrawing != null)
            {
                using (var memoryStream = new MemoryStream(EllipseDrawing))
                {
                    _strokesEllipse = new StrokeCollection(memoryStream);
                }
            }
            else
            {
                _strokesEllipse = new StrokeCollection();
            } 

            (_strokesEllipse as INotifyCollectionChanged).CollectionChanged += new NotifyCollectionChangedEventHandler(MainWindowsViewModel_CollectionChanged);
        }
The handler method of this event is as follows – [Note – Code to save byte array in database and retrieve it from database is skipped]

void MainWindowsViewModel_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)        {
            StrokesEllipse = ((StrokeCollection)sender);
            using (var memoryStream = new MemoryStream())
            {
                StrokesEllipse.Save(memoryStream);
                //convert memory stream to  array
                EllipseDrawing =  memoryStream.ToArray();
                //save the above array to say - database
            }
        }

The Properties defined as follow –
#region Properties 

        public StrokeCollection StrokesEllipse
        {
            get
            {
                return _strokesEllipse;
            }
            set
            {
                _strokesEllipse = value;
                RaisePropertyChanged("StrokesEllipse");
            }
        }
 
        public byte[] EllipseDrawing
        {
            get;
            set;
        }

        #endregion 

Finally attach the view model to XAML – in XAML.cs –
public MainWindow()       
{

            InitializeComponent();
            this.DataContext = new MainWindowsViewModel();
        }

Run the application and you should be able to get the byte array of StrokesCollection of InkCanvas in View model property.

 

This byte array can be saved to database for future purpose which I avoided here to keep it simple and focused on StrokCollection binding in MVVM.

Hope this helps.
Cheers…
Happy Stroking!!!

2 comments:

  1. Hi. May I know how to clear the strokes?

    ReplyDelete
    Replies
    1. Hi,
      you just need to put this line:
      StrokesEllipse.Clear();

      Delete