Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
898 views
in Technique[技术] by (71.8m points)

wpf - Slider ScrollViewer in a touch interface not working properly

In WPF I've got the following XAML:

<ScrollViewer Canvas.Left="2266" Canvas.Top="428" Height="378" Name="scrollViewer1" Width="728" PanningMode="VerticalOnly" PanningRatio="2">
    <Canvas Height="1732.593" Width="507.667">
        <Slider Height="40.668" x:Name="slider1" Width="507.667" Style="{DynamicResource SliderStyle1}" Canvas.Left="15" Canvas.Top="150" />
        </Slider>
    </Canvas>
</ScrollViewer>

It's a ScrollViewer containing a Slider. I'm using the following on a touch-screen, and I'm using the panning even to scroll the ScrollViewer vertically. When PanningMode="VerticalOnly" is set, the slider stops working!

I'm assuming the ScollViewer is consuming the touchslide event and handling it before the slider does (but I think I'm wrong on this front).

Is there any workaround for this?

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

I just solved this issue in our app.

What is happening is that the ScrollViewer captures the TouchDevice in its PreviewTouchMove handler, which "steals" the TouchDevice from other controls and prevents them from receiving any PreviewTouchMove or TouchMove events.

In order to work around this, you need to implement a custom Thumb control that captures the TouchDevice in the PreviewTouchDown event and stores a reference to it until the PreviewTouchUp event occurs. Then the control can "steal" the capture back in its LostTouchCapture handler, when appropriate. Here is some brief code:

public class CustomThumb : Thumb
{
    private TouchDevice currentDevice = null;

    protected override void OnPreviewTouchDown(TouchEventArgs e)
    {
        // Release any previous capture
        ReleaseCurrentDevice();
        // Capture the new touch
        CaptureCurrentDevice(e);
    }

    protected override void OnPreviewTouchUp(TouchEventArgs e)
    {
        ReleaseCurrentDevice();
    }

    protected override void OnLostTouchCapture(TouchEventArgs e)
    {
        // Only re-capture if the reference is not null
        // This way we avoid re-capturing after calling ReleaseCurrentDevice()
        if (currentDevice != null)
        {
            CaptureCurrentDevice(e);
        }
    }

    private void ReleaseCurrentDevice()
    {
        if (currentDevice != null)
        {
            // Set the reference to null so that we don't re-capture in the OnLostTouchCapture() method
            var temp = currentDevice;
            currentDevice = null;
            ReleaseTouchCapture(temp);
        }
    }

    private void CaptureCurrentDevice(TouchEventArgs e)
    {
        bool gotTouch = CaptureTouch(e.TouchDevice);
        if (gotTouch)
        {
            currentDevice = e.TouchDevice;
        }
    }
}

Then you will need to re-template the Slider to use the CustomThumb instead of the default Thumb control.


与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...