Is there a way to detect that ScrollViwer of ListView is in scrolling mode and stopped scrolling. In windows phone 8.1 ListView we can not get reference of the scrollviewer.
Any one done it in windows phone 8.1 WinRT app?
Once the ListView is Loaded you can get the ScrollViewer like this:
var sv = (ScrollViewer)VisualTreeHelper.GetChild(VisualTreeHelper.GetChild(this.ListV, 0), 0);
Edit
As Romasz suggested, once you get the ScrollViewer, you can use its ViewChanged event, to monitor when it is scrolling and when it stops.
Also, here's the generic extension method that I use for traversing the visual tree:
// The method traverses the visual tree lazily, layer by layer
// and returns the objects of the desired type
public static IEnumerable<T> GetChildrenOfType<T>(this DependencyObject start) where T : class
{
var queue = new Queue<DependencyObject>();
queue.Enqueue(start);
while (queue.Count > 0) {
var item = queue.Dequeue();
var realItem = item as T;
if (realItem != null) {
yield return realItem;
}
int count = VisualTreeHelper.GetChildrenCount(item);
for (int i = 0; i < count; i++) {
queue.Enqueue(VisualTreeHelper.GetChild(item, i));
}
}
}
To get the ScrollViewer using this methos, do this:
var sv = yourListView.GetChildrenOfType<ScrollViewer>().First();
You can find the ScrollViewer of your ListView by using VisualTreeHelper. For example like this:
// method to pull out a ScrollViewer
public static ScrollViewer GetScrollViewer(DependencyObject depObj)
{
if (depObj is ScrollViewer) return depObj as ScrollViewer;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
var child = VisualTreeHelper.GetChild(depObj, i);
var result = GetScrollViewer(child);
if (result != null) return result;
}
return null;
}
Once you have a ScrollViewer you can subscribe to its events:
GetScrollViewer(yourListView).ViewChanged += yourEvent_ViewChanged;
You must load data to listview before getting scrollview. If listview has empty row then scrollview you get will be null.
Related
By default the expander chevron is placed on the right:
<Expander
Header="This text is in the header"
Content="This is in the content"/>
How can I make the chevron be on the left of the header text?
Looking at the Expander class docs I wasn't able to find promising ExpanderChevron styles.
Looking at the Live Visual Tree I can see the chevron is in the second column of a grid. I looked at trying to override the column via a style, but couldn't figure it out.
You have two options.
The first option is to create a custom template. You could copy the default template for the ToggleButton from GitHub and edit as per your requirements.
The second option is to create your own custom Expander control that extends the existing one and programmatically move the elements:
public class CustomExpander : Expander
{
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
ToggleButton tb = GetTemplateChild("ExpanderHeader") as ToggleButton;
if (tb != null)
tb.Loaded += TbLoaded;
}
private void TbLoaded(object sender, RoutedEventArgs e)
{
ToggleButton tb = (ToggleButton)sender;
tb.Padding = new Thickness(0, 0, 16, 0);
tb.Loaded -= TbLoaded;
ContentPresenter cp = FindVisualChild<ContentPresenter>(tb);
Border border = FindVisualChild<Border>(tb);
if (cp != null && border != null)
{
Grid.SetColumn(cp, 1);
Grid.SetColumn(border, 0);
border.Margin = new Thickness(8, 0, 20, 0);
}
}
private static T FindVisualChild<T>(DependencyObject visual) where T : DependencyObject
{
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(visual); i++)
{
DependencyObject child = VisualTreeHelper.GetChild(visual, i);
if (child != null)
{
T correctlyTyped = child as T;
if (correctlyTyped != null)
return correctlyTyped;
T descendent = FindVisualChild<T>(child);
if (descendent != null)
return descendent;
}
}
return null;
}
}
Don't forget to update your XAML markup to use your custom control:
<local:CustomExpander Header="This text is in the header" Content="This is in the content" />
I'm trying to modify the below script so that it will automatically drop the first instance of "_item" and snap it to the nearest "slot"
The code works great except I cannot find a way to make it drop the item without the user clicking on it first. This is not my script. You can see it in action here- http://www.freeactionscript.com/2008/11/drag-drop-snap-inventory-system-v2/
Any help greatly appreciated, thanks!
/**
* Drag, Drop and Snap Inventory System
*
* Version: 2.0
* Author: Philip Radvan
* URL: http://www.freeactionscript.com
*/
var slots_array:Array = new Array(slot0, slot1, slot2, slot3, slot4, slot5, slot6, slot7, slot8, slot9, slot10, slot11, slot12, slot13, slot14, slot15);
var items_array:Array;
var uniqueItemId:Number = 0;
//
//start dragging
function dragItem(_item:Object):Void
{
//save position before dragging
_item.nowX = _item._x;
_item.nowY = _item._y;
//drag
_item.startDrag(true);
_item.onMouseMove = updateDrag;
}
//stop dragging
function dropItem(_item:Object):Void
{
//stop dragging
_item.stopDrag();
//delete mouse event
delete _item.onMouseMove;
//run loop on slots array
for (i=0; i<slots_array.length; i++)
{
//set temp slot var
currentSlot = eval(slots_array[i]);
//check slot hittest and slot itemID; if item is over slot and slot is empty, drop
if ((eval(_item._droptarget) == currentSlot) && (currentSlot.itemID == "empty"))
{
//place item in slot
_item._x = currentSlot._x;
_item._y = currentSlot._y;
//update current slot itemID
currentSlot.itemID = this;
//update previous slot itemID
temp = eval(_item.slotID);
temp.itemID = "empty";
//update current item slotID
_item.slotID = currentSlot.myName;
//item moved, end loop
return;
}
else
{
//return item to previous position if: item is NOT over slot or slot is NOT empty
_item._x = _item.nowX;
_item._y = _item.nowY;
}
}
}
/*
* updateAfterEven re-renders the screen
*/
function updateDrag():Void
{
updateAfterEvent();
}
/*
* Create Slots
*/
for (i=0; i<slots_array.length; i++)
{
var _currentSlot = slots_array[i];
_currentSlot.itemID = "empty";
_currentSlot.num = i;
_currentSlot.myName = "slot"+i;
}
/*
* Create Item
*/
function createInventoryItem()
{
//attach item to stage
var _item = attachMovie("item", "item"+uniqueItemId, _root.getNextHighestDepth());
//set item position
_item._x = 280;
_item._y = 320;
//set item settings
_item.myName = "item"+uniqueItemId;
_item.slotID = "empty";
//make item a button
_item.onPress = function()
{
dragItem(this)
}
_item.onRelease = _item.onReleaseOutside = function()
{
dropItem(this);
}
//add item to array
items_array.push(_item);
//update unique Item Id
uniqueItemId++;
}
//button to create a new inventory item
create_item_btn.onRelease = function()
{
createInventoryItem();
}
Fixed it. Rather than modifying this one I wrote my own. Thanks everyone : )
By placing the hit test code on the movie clip "_item" itself, a small array loop sorts it's position on clip event load, and snaps it to the slot. Super easy.
I am trying to find a solution to allow a Hub to pan with the mouse when its reaches the left or right boundary. I have implemented the code below which i have gleaned from various sources.
` private void theHubPointerMoved(object sender, PointerRoutedEventArgs e)
{ Windows.UI.Xaml.Input.Pointer ptr = e.Pointer;
if (ptr.PointerDeviceType == Windows.Devices.Input.PointerDeviceType.Mouse)
{
Windows.UI.Input.PointerPoint ptrPt = e.GetCurrentPoint(null);
if (ptrPt.Position.X < this.ActualWidth - 20)
if (ptrPt.Position.X > 20)
{
//Do the SCROLLING HERE
var xcord = Math.Round(ptrPt.Position.X, 2);
var ycord = Math.Round(ptrPt.Position.Y, 2);
}
}
e.Handled = true;
}`
So it is relativley easy to see when the mouse is at the screen edge. I thought it would be easy to simply use the MyHub.ScrollViewer.ScrollToHorizontalOffset(xcord); but the Hub Scrollviewer doesnt expose this ScrollToHorizontalOffset function.
Can anyone assist?
Thanks.
Oh, it's exposed. If you can handle digging for it. Here's how:
http://xaml.codeplex.com/SourceControl/latest#Blog/201401-ScrollHub/MainPage.xaml.cs
In the example below, it is scrolling to a specific hub section. But you should be able to easily adapt it to your specific needs, I hope.
private void ScollHubToSection(Hub hub, HubSection section)
{
var visual = section.TransformToVisual(this.MyHub);
var point = visual.TransformPoint(new Point(0, 0));
var viewer = Helpers.FindChild<ScrollViewer>(hub, "ScrollViewer");
viewer.ChangeView(point.X, null, null);
}
Using this:
public class Helpers
{
public static T FindChild<T>(DependencyObject parent, string childName) where T : DependencyObject
{
if (parent == null) return null;
T foundChild = null;
int childrenCount = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < childrenCount; i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
T childType = child as T;
if (childType == null)
{
foundChild = FindChild<T>(child, childName);
if (foundChild != null) break;
}
else if (!string.IsNullOrEmpty(childName))
{
var frameworkElement = child as FrameworkElement;
if (frameworkElement != null && frameworkElement.Name == childName)
{
foundChild = (T)child;
break;
}
}
else
{
foundChild = (T)child;
break;
}
}
return foundChild;
}
}
Best of luck!
In my Windows 8 app, I am trying to change the text of a textblock inside a DataTemplate of a FlipView...
my FlipView datatemplate (simplified...) :
<FlipView.ItemTemplate>
<DataTemplate>
<TextBlock x:Name="test" />
</DataTemplate>
</FlipView.ItemTemplate>
I tried this solution : How do I access a control inside a XAML DataTemplate?
So my .cs :
var _Container = flipView.ItemContainerGenerator.ContainerFromItem(flipView.SelectedItem);
var _Children = AllChildren(_Container);
var myTextBlock= _Children.OfType<TextBlock>().FirstOrDefault(c => c.Name.Equals("test"));
myTextBlock.Text = "test";
with the method :
public List<Control> AllChildren(DependencyObject parent)
{
var _List = new List<Control>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var _Child = VisualTreeHelper.GetChild(parent, i);
if (_Child is Control)
_List.Add(_Child as Control);
_List.AddRange(AllChildren(_Child));
}
return _List;
}
But I get a NullReferenceException error : "{"Object reference not set to an instance of an object."}"
So it doesn't find my textblock...
Thanks
hello friend i have checked your code..and what i found is a very unnoticeable mistake..that is about the Control keyword..actually it is your type of control you want to search in your flipview..like textblock,textbox etc...you have to just change your AllChilderen Function like this and then all will work fine..
public List<TextBlock> AllChildren(DependencyObject parent)
{
var _List = new List<TextBlock>();
int j = VisualTreeHelper.GetChildrenCount(parent);
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var _Child = VisualTreeHelper.GetChild(parent, i);
if (_Child is TextBlock)
_List.Add(_Child as TextBlock);
_List.AddRange(AllChildren(_Child));
}
return _List;
}
hope it will help you..
I am developing a metro app where , I want to have a customized bar slide when the user clicks on something in the screen.
This is what i am talking about :-
--------------
| | |
| | | <----
| | |
---------------
main screen side
bar
In this side bar i want have some simple controls like image and text block etc..
1) How can i do this , any help would be appreciated
2) Its not against metro principles right ?
You could try to leverage a flyout like the settings flyout. You might want to look at Callisto.
You could otherwise include a Xaml element that above all others and toggle it's visibility along with a positioning right on the screen. How to position depends on what root element you're using. For positioning an element in a canvas add Canvas.Right="0" to the child element.
You can use PopUp.
have a look at this example,
http://code.msdn.microsoft.com/windowsapps/App-settings-sample-1f762f49
you can use following helper
WinRT Flyout Helper
public class FlyoutHelper
{
protected Popup m_Popup = new Popup();
public Popup Show(Popup popup, FrameworkElement button, double offset = 35d)
{
if (popup == null)
throw new Exception("Popup is not defined");
m_Popup = popup;
if (button == null)
throw new Exception("Button is not defined");
if (double.IsNaN(offset))
throw new Exception("Offset is not defined");
var _Child = popup.Child as FrameworkElement;
if (_Child == null)
throw new Exception("Popup.Child is not defined");
if (double.IsNaN(_Child.Height))
throw new Exception("Popup.Child.Height is not defined");
if (double.IsNaN(_Child.Width))
throw new Exception("Popup.Child.Width is not defined");
// get position of the button
var _Page = Window.Current.Content as Page;
var _Visual = button.TransformToVisual(_Page);
var _Point = _Visual.TransformPoint(new Point(0, 0));
var _Button = new
{
Top = _Point.Y,
Left = _Point.X,
Width = button.ActualWidth,
Height = button.ActualHeight,
};
// determine location
var _TargetTop = (_Button.Top + (_Button.Height / 2)) -
_Child.Height - offset;
var _TargetLeft = (_Button.Left + (_Button.Width / 2)) -
(_Child.Width / 2);
if ((_TargetLeft + _Child.Width) > Window.Current.Bounds.Width)
_TargetLeft = Window.Current.Bounds.Width - _Child.Width - offset;
if (_TargetLeft < 0)
_TargetLeft = offset;
// setup popup
popup.VerticalOffset = _TargetTop;
popup.HorizontalOffset = _TargetLeft;
// add pretty animation(s)
popup.ChildTransitions = new TransitionCollection
{
new EntranceThemeTransition
{
FromHorizontalOffset = 0,
FromVerticalOffset = 20
}
};
// setup
m_Popup.IsLightDismissEnabled = true;
m_Popup.IsOpen = true;
// handle when it closes
m_Popup.Closed -= popup_Closed;
m_Popup.Closed += popup_Closed;
// handle making it close
Window.Current.Activated -= Current_Activated;
Window.Current.Activated += Current_Activated;
// return
return m_Popup;
}
protected void Current_Activated(object sender, WindowActivatedEventArgs e)
{
if (m_Popup == null)
return;
if (e.WindowActivationState == CoreWindowActivationState.Deactivated)
m_Popup.IsOpen = false;
}
protected void popup_Closed(object sender, object e)
{
Window.Current.Activated -= Current_Activated;
if (m_Popup == null)
return;
m_Popup.IsOpen = false;
}
}
For this you can use CharmFlyout.
Here is the sample code http://code.msdn.microsoft.com/windowsapps/CharmFlyout-A-Metro-Flyout-25fe53b6