Azzarrel
Azzarrel

Reputation: 573

Set a Delay to a WPF Viewbox?

I have a Window with a Viewbox in it. Based on the content of my Viewbox resizing the Window can get quite 'stuttery'. I don't need to have the Viewbox resize its content in realtime, it would be sufficient to update the Viewbox once the user is done resizing the Window.

I couldn't find anything about this topic on google by myself.

Is there a way to 'delay' my Viewbox?

edit: if not, what would be the best way to simulate this behavior?

Best i could think about was to create a grid around the viewbox, create 2 Properties for width and height, bind them to both window and grid with a twoway Binding and then set a delay in the binding, so the grid and the viewbox in it will resize after the delay, but then I would have to set a pre-defined starting size for my window due to the properties.

Upvotes: 1

Views: 379

Answers (1)

kennyzx
kennyzx

Reputation: 12993

You can use a Canvas as the container for the ViewBox. (The direct container has to be a Grid, which gives the ViewBox a boundary to resize.)

Unlike Grid, Canvas uses absolute positioning, and it does not resize with the Window, so do its children.

<Grid x:Name="root">
    <Canvas>
        <Grid x:Name="innerGrid">
            <Viewbox>
                <Content here />
            </Viewbox>
        </Grid>
    </Canvas>
</Grid>

Then you can control when to resize the ViewBox (by resizing its direct container).

The following code is inspired by the comments. It uses a one-time Timer, the timer starts when user has finished manipulating, and the resizing takes place when the timer interval elapsed.

System.Timers.Timer timer; //Declare it as a class member, not a local field, so it won't get GC'ed. 
public MainWindow()
{
    InitializeComponent();
    timer = new System.Timers.Timer(1000);
    timer.AutoReset = false; //the Elapsed event should be one-shot
    timer.Elapsed += (o, e) =>
    {
        //Since this is running on a background thread you need to marshal it back to the UI thread.
        Dispatcher.BeginInvoke(new Action(() => {
            innerGrid.Width = root.ActualWidth;
            innerGrid.Height = root.ActualHeight;
        }));
    };

    this.SizeChanged += (o, e) =>
    {
        //restart the time if user is still manipulating the window             
        timer.Stop(); 
        timer.Start();
    };
}

Upvotes: 2

Related Questions