I have created a Windows 8 Store App using C# / XAML. My interface includes a scrollable list, which is rendered using an ScrollViewer. I would like to be able to handle manipulation events on the elements within the list, however, setting ManipulationMode to anything other than None on the list element causes my list to no longer scroll.
Here is a simplified version of the UI:
<ScrollViewer>
<Border/> <!-- these contain child content -->
<Border/>
<Border/>
<!-- Set ManipulationMode on an element in order to receive manipulation events -->
<!-- This causes the scroll viewer to stop working! -->
<Border ManipulationMode="All"
ManipulationDelta="..."/>
<Border/>
<Border/>
</ScrollViewer>
I understand that the WinRT ScrollViewer uses a special ManipulationMode of System for performance reasons, but I would like to have a vertically scrolling list, containing elements that respond to horizontal manipulation / gestures. Can anyone think of a creative workaround that would make this possible?
it may be long time but didn't find any good solution. I just achieved what I wanted very easily.
public MovableGrid()
{
ManipulationMode = ManipulationModes.TranslateX | ManipulationModes.System;
AddHandler(ManipulationDeltaEvent, new ManipulationDeltaEventHandler(UIElement_OnManipulationDelta), true);
AddHandler(ManipulationCompletedEvent, new ManipulationCompletedEventHandler(UIElement_OnManipulationCompleted), true);
}
I wanted my MovableGrid to be moved on X axis and I have list of MovableGrids which I wanted to be scrolled with scrollviewer. That's enough to do that.
What I have done was I put a transparent rectangle on top of the ScrollViewer and handle manipulations there. When I find the manipulation should scroll the ScrollViewer - I scroll the ScrollViewer using the ScrollToHorizontal/VerticalOffset() methods. On ManipulationStarted I also use VisualTreeHelper.FindElementsInHostCoordinates to check which item I could manipulate too and then I can decide whether to manipulate that item or not depending on various conditions. It's quite a bit of custom code though. You would also need to update the RenderTransform of the ScrollContentPresenter in the ScrollViewer when the user tries to drag farther than minimum/maximum offset to immitate the ScrollViewer default behavior, handle mouse scrollwheel etc. Nothing YOU could not handle of course. I could not find a better way unfortunately and I am interested if someone finds one.
EDIT* Another solution I thought of when trying to answer another similar question was to use another ScrollViewer as a child item and use its ViewChanged events instead of manipulation events.
EDIT 2*
Also with Windows 8.1 you get ManipulationModes.System which combined with other modes should allow you to handle manipulations inside of a ScrollViewer. Then you can call CancelDirectManipulations() on the manipulated element once you want its parent ScrollViewers to stop processing manipulations for pan&zoom.
Related
Since I cannot find any official documentation about it I need to ask this questions. Is there any way to animate grids on visibility change?
I have tried adding TransitionCollections to grids but it works only the first time that grid initialized.
I also tried this answer but it also wont work because Grid.Loaded event fires even if grid is collapsed.
You can use event Loaded(). Just add attributes in XAML
x:DeferLoadStrategy="Lazy" Visibility="Collapsed"
and element will be completely collapsed.
To load it use somewhere in C# code standart:
SomeHiddenElement.Visibility = Visibility.Visible;
Is it possible to apply UI virtualization to ScrollViewer in WinRT. In my application I am creating a line chart with the help of Polyline(Polyline embedded inside a scrollviewver). But in the current case, If it come more than 500 points. It blocks the UI during the time of interacting with the Map. So what I am trying to achieve is to apply kind of UI virtualization to scroll view. If anyone had any idea to solve this please help me.
The way I would handle a Polyline is I would break its data into sections, perhaps screen-wide ones (assuming horizontal-only scrolling), put a Canvas inside of the ScrollViewer, make the size (Width) of the Canvas the total size of the chart and put a few (say 5) Polyline controls in it and then on the ViewChanged event update the Polyline controls' Canvas.Left and Points properties to correspond to the area around the current view port of the ScrollViewer. That should give you smooth scrolling. Just don't add/remove or update the controls on each ViewChanged and only update Canvas.Left and Points when you need to - that is when you don't have a Polyline ready to display next to the current view port.
I know the title is a little confusing, but the best way to describe what I'm after is by running the Weather metro app on the Consumer Preview; as you scroll horizontally, you'll note that the section headings kind of move around and stay on top of the relevant content, and then fade out as you cross over into a new section. (The main background for the first section also kind of does this)
My question is, how would I go about replicating this behavior in a WinRT app of my own? Are there any existing controls I can leverage or would I have to essentially rewrite it all?
This looks just like a ScrollViewer - you would handle the ViewChanged event and depending on the scroll offset - change the opacity of overlaid static TextBlocks and completely hide the ones that scroll once you cross specific tresholds. I don't think there is anything like that that does it, but I can build it.
I've got a WrapPanel which will contain several different custom UserControls. Depending on the scenario, I may need to filter down which UserControls are visible. My goal is that I can switch which controls are visible on the fly by showing/hiding the controls that need to be filtered - thus shifting the controls that are left showing, to the top-left of the panel.
Right now I am simply setting the Visibility property of the control to Visibility.Collapsed when I don't want them to appear. I thought that because I was using a WrapPanel, the rest of the controls would shift to the top-left of the panel.
Instead, after hiding some of the UserControls, the controls that are still visible stay exactly where they were before, and I am left with gaps between the controls that are still showing. I've opened my app in Silverlight Spy, and it shows that the UserControls are still actually there (which makes sense) but are simply invisible.
So my question is:
Is there a way that I can show/hide UserControls within a WrapPanel which allows the still-visible UserControls to slide to their new positions (all shifting towards the top left - similar to a StackPanel)?
I've debated removing the UserControls completely from the WrapPanel (I think this would work) and storing them in memory until they are needed. Then if I wanted to show/hide other controls, I would get them from my in-memory object. It seems like there should be a better way to do this though.
If anyone has any suggestions or advice, it would be greatly appreciated. Thanks!
-Lloyd
UPDATE:
XAML: (very simple)
<toolkit:WrapPanel x:Name="MyLayout" Height="300" HorizontalAlignment="Left" VerticalAlignment="Top" Width="400" />
Code-Behind: The UserControls are getting added dynamically:
MyLayout.Children.Add(oUserControl)
And they are getting set to collapsed dynamically as well:
oUserControl.Visibility = Visibility.Collapsed
I think I've found the problem. We added the WrapPanel to a ScrollViewer recently, and when I took the ScrollViewer out I was able to achieve the functionality I wanted.
I'm not sure why the ScrollViewer would have that effect though?
Also, I've found that I can leave the ScrollViewer in place and simply call .Measure() on the WrapPanel to update the layout.
Neither option makes 100% sense to me, but they do both seem to work.
How can I find the component in a ScrollViewer that handles the RequestBringIntoView event?
It isn't exposed on the two ScrollBar parts (not directly, anyway).
Thanks for any pointers...
UPDATE: Related: Can I get the ScrollContentPresenter part of the ScrollViewer? How?
Thanks --
Bigger picture:
We have a large Canvas contained in a ScrollViewer. At runtime, an arbitrary number of UserControls (I'll call them 'Blobs') are added to the canvas from the db. Their position and content come from the db. A user can 'select' a blob by clicking on it, and its appearance changes to indicate it is selected.
If the user uses a scrollbar to move the selected blob out of view, then clicks on another blob, the Canvas is scrolled so the previously-out-of-view blob is in view again. I assume this is due to some object raising the RequestBringIntoView, and the ScrollViewer is handling it.
Hope this makes sense...
Yet more info:
Added a handler (sb_ValueChanged) to the Scrollviewer's scrollbar ValueChanged event. Here's the stack from the mouse click that precipitates the scrolling:
OurControl.sb_ValueChanged() System.Windows.dll!System.Windows.Controls.Primitives.RangeBase.OnValueChanged() System.Windows.dll!System.Windows.Controls.Primitives.ScrollBar.OnValueChanged() System.Windows.dll!System.Windows.Controls.Primitives.RangeBase.OnValuePropertyChanged()
System.Windows.dll!System.Windows.DependencyObject.RaisePropertyChangeNotifications()
System.Windows.dll!System.Windows.DependencyObject.UpdateEffectiveValue()
System.Windows.dll!System.Windows.DependencyObject.SetValueInternal()
System.Windows.dll!System.Windows.DependencyObject.SetValue()
System.Windows.dll!System.Windows.Controls.ScrollViewer.InvalidateScrollInfo() System.Windows.dll!System.Windows.Controls.ScrollContentPresenter.VerifyScrollData()
System.Windows.dll!System.Windows.Controls.ScrollContentPresenter.ArrangeOverride()
System.Windows.dll!System.Windows.FrameworkElement.ArrangeOverride()
If only I could find out what the FrameworkElement that starts the mischief actually is...
Sorry... it doesn't seems to exist like it does in WPF. Check this link for a handy solution.
Update: Ok... for this you might need to walk the visual tree and some sort of recursive search need to be done. However, assuming you are using the default template for the scrollviewer as seen here, you can directly ask for the ScrollContentPresenter with something like this:
var BorderChild = VisualTreeHelper.GetChild(MyScrollViewer, 0);
var GridChild = VisualTreeHelper.GetChild(BorderChild, 0);
var ScrollContentPresenterChild = VisualTreeHelper.GetChild(GridChild, 0);