0
votes

I'm learning how to develop UWP apps and I'm using Microsoft's documentation as tutorials/research.

I want to have an InkCanvas design similar to OneNote where the InkCanvas height and width can expand (as you're writing/drawing and reach the end of the window size) and can shrink (when you erase ink strokes and the extra size can decrease based on the position of the ink strokes until you get back to the original size).

I'm able to increase the InkCanvas width and height, but can't decrease when erasing ink strokes.

Here is a MainPage.xaml code:

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

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

    <TextBlock Text="Heading"
                   FontSize="36"
                   FontWeight="Bold"
                   Margin="10"
                   Grid.Column="0"
                   Grid.Row="0"/>

    <Grid BorderBrush="Red"
                    BorderThickness="2"
                    Margin="10"
                    Grid.Column="0"
                    Grid.Row="1">
        <ScrollViewer HorizontalScrollBarVisibility="Auto"
                      HorizontalScrollMode="Enabled"
                      VerticalScrollBarVisibility="Auto"
                      VerticalScrollMode="Enabled" >

            <Grid BorderBrush="Blue"
                    BorderThickness="2"
                    Margin="1">
                <InkCanvas Name="inkCanvas"/>
            </Grid>
        </ScrollViewer>

    </Grid>

And the MainPage.cs code:

public MainPage()
    {
        this.InitializeComponent();
        nkCanvas.InkPresenter.StrokeInput.StrokeEnded += adjustInkCanvasSize;
    }

    private  async void adjustInkCanvasSize(InkStrokeInput sender, PointerEventArgs args)
    {
        await Task.Delay(100);

        var XBound = inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Bottom;
        if (XBound > inkCanvas.ActualHeight - 200)
            inkCanvas.Height = XBound + 200;

        var YBound = inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Right;
        if (YBound > inkCanvas.ActualWidth - 200)
            inkCanvas.Width = YBound + 200;
     }

The c# code also came from another stackoverflow solution, but not able to figure out the "decrease" part.

Any help would be much appreciated. Thanks

1

1 Answers

0
votes

If you want the InkCanvas control to shrink when you erase ink strokes and the extra size can decrease based on the position of the ink strokes until the original size, you need to add the InkPresenter.StrokesErased event to manage the size of the InkCanvas control. For example:

Here is a MainPage.xaml code( To facilitate testing, I added the mouse support):

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="*" />
        <ColumnDefinition Width="*" />
    </Grid.ColumnDefinitions>

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

    <TextBlock Text="Heading"
               FontSize="36"
               FontWeight="Bold"
               Margin="10"
               Grid.Column="0"
               Grid.Row="0"/>

    <Grid BorderBrush="Red"
                BorderThickness="2"
                Margin="10"
                Grid.Column="0"
                Grid.Row="1">
        <Grid.RowDefinitions>
            <RowDefinition Height="auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>

        <InkToolbar x:Name="inkToolbar" VerticalAlignment="Top" Margin="10,0,10,0"
                            TargetInkCanvas="{x:Bind inkCanvas}" Grid.Row="0"/>
        <ScrollViewer HorizontalScrollBarVisibility="Auto"
                  HorizontalScrollMode="Enabled" Grid.Row="1"
                  VerticalScrollBarVisibility="Auto"
                  VerticalScrollMode="Enabled" >

            <Grid BorderBrush="Blue"
                BorderThickness="2"
                Margin="1">
                
                <InkCanvas Name="inkCanvas" />
                
            </Grid>
        </ScrollViewer>

    </Grid>
</Grid>

And the MainPage.cs code:

public sealed partial class MainPage : Page
{
    private double originalX; //The original size
    private double originalY;
    private double maxX=0.0; 
    private double maxY=0.0;
    private bool flag = true;
    public MainPage()
    {
        this.InitializeComponent();

        inkCanvas.InkPresenter.InputDeviceTypes = CoreInputDeviceTypes.Mouse | CoreInputDeviceTypes.Touch |
            CoreInputDeviceTypes.Pen;
        inkCanvas.InkPresenter.StrokeInput.StrokeEnded += adjustInkCanvasSize;
        inkCanvas.InkPresenter.StrokesErased += InkPresenter_StrokesErased;
    }

    private async void InkPresenter_StrokesErased(InkPresenter sender, InkStrokesErasedEventArgs args)
    {
        await Task.Delay(100);

        //The coordinate of the lower right corner of the erased ink stoke
        var erasedInkX= args.Strokes.ElementAt(0).BoundingRect.Bottom;
        var erasedInkY = args.Strokes.ElementAt(0).BoundingRect.Right;
        
        var XBound = inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Bottom;
        if (erasedInkX >=maxX&&XBound < inkCanvas.ActualHeight + 100)
        {
            if (XBound - 100 > originalX)
                inkCanvas.Height = XBound - 100;
            else
                inkCanvas.Height = originalX;  //The size of InkCanvas shrinks to the original size.

            maxX = inkCanvas.Height;
        }
            
        var YBound = inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Right;
        if (erasedInkY>=maxY&&YBound < inkCanvas.ActualWidth + 100)
        {
            if (YBound - 100 > originalY)
            {
                inkCanvas.Width = YBound - 100;
            }
            else
                inkCanvas.Width = originalY;

            maxY = inkCanvas.Width;
        }
    }

    private async void adjustInkCanvasSize(InkStrokeInput sender, PointerEventArgs args)
    {
        await Task.Delay(100);

        if(flag)
        {
            flag = false;
            originalX = inkCanvas.ActualHeight;  //Get the original size 
            originalY = inkCanvas.ActualWidth;
        }
        var XBound = inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Bottom;
        if (XBound > maxX)
            maxX = XBound;  //maxX and maxY always hold the maximum size of StrokeContainer

        if (XBound > inkCanvas.ActualHeight - 200)
            inkCanvas.Height = XBound + 200;

        var YBound = inkCanvas.InkPresenter.StrokeContainer.BoundingRect.Right;
        if (YBound > maxY)
            maxY = YBound;

        if (YBound > inkCanvas.ActualWidth - 200)
            inkCanvas.Width = YBound + 200;
    }
}