TouchEventArgs e.OrigionalSouce for TouchMove Event is different from TouchDown Event - c#

I am trying to perform a drag and drop in a list view. Problem is when I select an item with touch and move it. So firstly the TouchDown event executes which works fine. The e.OriginalSource for TouchEventArgs is a border when I keep a break point, I am able to find the parent as a listviewitem using FindParent method.
Problem is when the debugger comes to TouchMove Event, the TouchEventArgs, e.OriginalSource is being changed to ScrollViewer. I don't know how its changed. As a result the find parent returns null instead of the listviewitem. Please help.
Please see the TouchDown and TouchMove conditions in the GlobalHandler event in the code behind.
xaml:
<ListView
Name="RunSetupListView"
Grid.Row="0"
Grid.Column="0"
Grid.ColumnSpan="3"
Style="{StaticResource RunSetupDisplayListViewStyle}"
ItemsSource="{Binding RunSetupInfoList}"
AlternationCount="100"
LayoutUpdated="RunSetupListView_LayoutUpdated"
PreviewMouseLeftButtonDown="GlobalHandler"
PreviewTouchDown="GlobalHandler"
PreviewMouseLeftButtonUp="GlobalHandler"
PreviewTouchUp="GlobalHandler"
PreviewMouseMove="GlobalHandler"
PreviewTouchMove="GlobalHandler"
DragEnter="RunSetupListView_DragEnter"
DragOver="RunSetupListView_DragOver"
Drop="RunSetupListView_Drop"
DragLeave="RunSetupListView_DragLeave"/>
Code Behind
private void GlobalHandler(object sender, InputEventArgs e)
{
if (e.RoutedEvent == PreviewMouseLeftButtonDownEvent)
{
var args = e as MouseButtonEventArgs;
var listViewItem =
VisualTreeHelperUtils.FindParent<ListViewItem>((DependencyObject)args.OriginalSource);
if (listViewItem != null)
{
SelectedDragItem = listViewItem;
// Log start point
StartPoint = args.GetPosition(null);
}
}
if (e.RoutedEvent == PreviewTouchDownEvent)
{
var args = e as TouchEventArgs;
var listViewItem =
VisualTreeHelperUtils.FindParent<ListViewItem>((DependencyObject)args.OriginalSource);
if (listViewItem != null)
{
SelectedDragItem = listViewItem;
// Log start point
StartPoint = args.GetTouchPoint(null).Position;
IsScreenTouched = true;
}
}
if (e.RoutedEvent == PreviewMouseLeftButtonUpEvent)
{
// Reest in case only a click occurs in the tree view WITHOUT a drag event
StartPoint = null;
SelectedDragItem = null;
}
if (e.RoutedEvent == PreviewTouchUpEvent)
{
// Reest in case only a click occurs in the tree view WITHOUT a drag event
StartPoint = null;
SelectedDragItem = null;
IsScreenTouched = false;
}
if (e.RoutedEvent == PreviewMouseMoveEvent)
{
var args = e as MouseEventArgs;
if (!(sender is ListView))
return;
// only for left button down and if we received a mouse down
// event in the listview... sometimes this event will still get processed
// even if you click outside the listview but then drag the mouse into the listview
if (args.LeftButton == MouseButtonState.Pressed && StartPoint != null && SelectedDragItem != null)
{
var mousePos = args.GetPosition(null);
var diff = StartPoint.Value - mousePos;
// Once the drag has been dragged far enough... prevents a drag from happening
// from simply clicking the item
if ((Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance
|| Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance) &&
!_inDragMode)
{
var listView = sender as ListView;
var listViewItem =
VisualTreeHelperUtils.FindParent<ListViewItem>((DependencyObject)args.OriginalSource);
if (listViewItem == null)
{
return;
}
m_AdornerLayer = InitializeAdornerLayer(listViewItem, listView);
UpdateDragAdornerLocation(args.GetPosition(listView));
mousePoint = mousePos;
_inDragMode = true;
DataObject dragData = new DataObject(listViewItem.Content as DNA2RunInfoDisplay);
listView.CaptureMouse();
DragDrop.DoDragDrop(listViewItem, dragData, DragDropEffects.Move);
_inDragMode = false;
// Reset this here... the mouse up event DOES NOT get raised if we do a drag/drop effect
StartPoint = null;
SelectedDragItem = null;
}
}
}
if (e.RoutedEvent == PreviewTouchMoveEvent)
{
var args = e as TouchEventArgs;
if (!(sender is ListView))
return;
// only for left button down and if we received a mouse down
// event in the listview... sometimes this event will still get processed
// even if you click outside the listview but then drag the mouse into the listview
if (IsScreenTouched && StartPoint != null && SelectedDragItem != null)
{
var mousePos = args.GetTouchPoint(null).Position;
var diff = StartPoint.Value - mousePos;
// Once the drag has been dragged far enough... prevents a drag from happening
// from simply clicking the item
if ((Math.Abs(diff.X) > SystemParameters.MinimumHorizontalDragDistance
|| Math.Abs(diff.Y) > SystemParameters.MinimumVerticalDragDistance) &&
!_inDragMode)
{
var listView = sender as ListView;
//This is the problem the args OriginalSource is a scroll viewer here
var listViewItem =
VisualTreeHelperUtils.FindParent<ListViewItem>((DependencyObject)args.OriginalSource);
if (listViewItem == null)
{
return;
}
m_AdornerLayer = InitializeAdornerLayer(listViewItem, listView);
UpdateDragAdornerLocation(args.GetTouchPoint(listView).Position);
mousePoint = mousePos;
_inDragMode = true;
DataObject dragData = new DataObject(listViewItem.Content as DNA2RunInfoDisplay);
listView.CaptureTouch(args.TouchDevice);
DragDrop.DoDragDrop(listViewItem, dragData, DragDropEffects.Move);
_inDragMode = false;
IsScreenTouched = false;
// Reset this here... the mouse up event DOES NOT get raised if we do a drag/drop effect
StartPoint = null;
SelectedDragItem = null;
}
}
}
}

Here is the entire source code in case if it helps someone.
private void DoDragandDrop(ListViewItem item, DataObject obj, DragDropEffects effect)
{
if ((item != null) && (obj != null))
{
DragDrop.DoDragDrop(item, obj, effect);
}
}
private void GlobalHandler(object sender, InputEventArgs e)
{
Point? startPoint;
if (object.ReferenceEquals(e.RoutedEvent, UIElement.PreviewMouseLeftButtonDownEvent))
{
MouseButtonEventArgs args = e as MouseButtonEventArgs;
ListViewItem item = VisualTreeHelperUtils.FindParent<ListViewItem>((DependencyObject) args.OriginalSource);
if (item != null)
{
DNA2RunInfoDisplay content = item.Content as DNA2RunInfoDisplay;
if ((content != null) && (content.PlateIndex == -2147483648))
{
return;
}
this.SelectedDragItem = item;
this.StartPoint = new Point?(args.GetPosition(null));
}
}
if (object.ReferenceEquals(e.RoutedEvent, UIElement.PreviewTouchDownEvent))
{
ListView listView = sender as ListView;
TouchEventArgs args2 = e as TouchEventArgs;
object selectedItem = this.RunSetupListView.SelectedItem;
ListViewItem itemToDrag = VisualTreeHelperUtils.FindParent<ListViewItem>((DependencyObject) args2.OriginalSource);
if (itemToDrag != null)
{
itemToDrag.Focus();
this.SelectedDragItem = itemToDrag;
this.StartPoint = new Point?(args2.GetTouchPoint(null).Position);
this.m_AdornerLayer = this.InitializeAdornerLayer(itemToDrag, listView);
this.UpdateDragAdornerLocation(args2.GetTouchPoint(listView).Position);
if (this.SelectedDragItem.Content != BindingOperations.DisconnectedSource)
{
this.dataObject = new DataObject(this.SelectedDragItem.Content as DNA2RunInfoDisplay);
}
listView.CaptureTouch(args2.TouchDevice);
}
}
if (object.ReferenceEquals(e.RoutedEvent, UIElement.PreviewMouseLeftButtonUpEvent))
{
startPoint = null;
this.StartPoint = startPoint;
this.SelectedDragItem = null;
}
if (object.ReferenceEquals(e.RoutedEvent, UIElement.PreviewTouchUpEvent))
{
startPoint = null;
this.StartPoint = startPoint;
this.SelectedDragItem = null;
this.dataObject = null;
if (this.m_DragAdorner != null)
{
this.m_DragAdorner.Visibility = Visibility.Collapsed;
}
}
if (object.ReferenceEquals(e.RoutedEvent, UIElement.PreviewMouseMoveEvent))
{
MouseEventArgs args3 = e as MouseEventArgs;
if (!(sender is ListView))
{
return;
}
if ((args3.LeftButton == MouseButtonState.Pressed) && ((this.StartPoint != null) && (this.SelectedDragItem != null)))
{
Point position = args3.GetPosition(null);
startPoint = this.StartPoint;
Vector vector = startPoint.Value - position;
if (((Math.Abs(vector.get_X()) > SystemParameters.MinimumHorizontalDragDistance) || (Math.Abs(vector.get_Y()) > SystemParameters.MinimumVerticalDragDistance)) && !this._inDragMode)
{
ListView listView = sender as ListView;
ListViewItem selectedDragItem = this.SelectedDragItem;
if (selectedDragItem == null)
{
return;
}
this.m_AdornerLayer = this.InitializeAdornerLayer(selectedDragItem, listView);
this.UpdateDragAdornerLocation(args3.GetPosition(listView));
this.mousePoint = position;
this._inDragMode = true;
listView.CaptureMouse();
DragDrop.DoDragDrop(selectedDragItem, new DataObject(selectedDragItem.Content as DNA2RunInfoDisplay), DragDropEffects.Move);
listView.ReleaseMouseCapture();
this._inDragMode = false;
startPoint = null;
this.StartPoint = startPoint;
this.SelectedDragItem = null;
}
}
}
if (object.ReferenceEquals(e.RoutedEvent, UIElement.PreviewTouchMoveEvent))
{
Point position = (e as TouchEventArgs).GetTouchPoint(null).Position;
startPoint = this.StartPoint;
if ((startPoint == null) || (this.SelectedDragItem == null))
{
if (this.m_DragAdorner != null)
{
this.m_DragAdorner.Visibility = Visibility.Collapsed;
}
}
else
{
startPoint = this.StartPoint;
Point point3 = position;
if ((startPoint != null) ? ((startPoint != null) ? (startPoint.GetValueOrDefault() != point3) : false) : true)
{
startPoint = this.StartPoint;
Vector vector2 = startPoint.Value - position;
if (((Math.Abs(vector2.get_X()) > SystemParameters.MinimumHorizontalDragDistance) || (Math.Abs(vector2.get_Y()) > SystemParameters.MinimumVerticalDragDistance)) && (this.dataObject != null))
{
this.DoDragandDrop(this.SelectedDragItem, this.dataObject, DragDropEffects.Move);
}
}
}
this.SelectedDragItem = null;
startPoint = null;
this.StartPoint = startPoint;
}
}
private void HandleDragEvent(object sender, DragEventArgs e)
{
if (!e.Data.GetDataPresent(typeof(DNA2RunInfoDisplay)))
{
e.Effects = DragDropEffects.None;
e.Handled = true;
}
else
{
DependencyObject originalSource = e.OriginalSource as DependencyObject;
if (originalSource == null)
{
e.Effects = DragDropEffects.None;
e.Handled = true;
}
else
{
ListViewItem item = VisualTreeHelperUtils.FindParent<ListViewItem>(originalSource);
if (item == null)
{
e.Effects = DragDropEffects.None;
e.Handled = true;
}
else
{
if ((item.Content as DNA2RunInfoDisplay).RunState == DNA2RunStates.Unassigned)
{
e.Effects = DragDropEffects.None;
}
else
{
ListView relativeTo = sender as ListView;
if (relativeTo != null)
{
Point point = item.TransformToAncestor((Visual) relativeTo).Transform(new Point(0.0, 0.0));
this.UpdateDragAdornerLocation(new Point(point.get_X(), e.GetPosition(relativeTo).get_Y()));
this.m_DragAdorner.Visibility = Visibility.Visible;
}
e.Effects = e.AllowedEffects;
}
e.Handled = true;
}
}
}
}
private AdornerLayer InitializeAdornerLayer(ListViewItem itemToDrag, ListView listView)
{
VisualBrush brush = new VisualBrush(itemToDrag);
this.m_DragAdorner = new BRDragAdornerWithVisualBrush(listView, itemToDrag.RenderSize, brush);
AdornerLayer adornerLayer = AdornerLayer.GetAdornerLayer(listView);
adornerLayer.Add(this.m_DragAdorner);
return adornerLayer;
}
private void RunSetupListView_DragEnter(object sender, DragEventArgs e)
{
this.HandleDragEvent(sender, e);
}
private void RunSetupListView_DragLeave(object sender, DragEventArgs e)
{
if (this.m_DragAdorner != null)
{
this.m_DragAdorner.Visibility = Visibility.Collapsed;
}
}
private void RunSetupListView_DragOver(object sender, DragEventArgs e)
{
FrameworkElement depObj = sender as FrameworkElement;
if (depObj != null)
{
ScrollViewer firstVisualChild = VisualTreeHelperUtils.GetFirstVisualChild<ScrollViewer>(depObj);
if (firstVisualChild != null)
{
double num = e.GetPosition(depObj).get_Y();
if (num < 30.0)
{
firstVisualChild.ScrollToVerticalOffset(firstVisualChild.VerticalOffset - 20.0);
}
else if (num > (depObj.ActualHeight - 30.0))
{
firstVisualChild.ScrollToVerticalOffset(firstVisualChild.VerticalOffset + 20.0);
}
this.HandleDragEvent(sender, e);
}
}
}
private void RunSetupListView_Drop(object sender, DragEventArgs e)
{
try
{
this._inDragMode = false;
if (e.Data.GetDataPresent(typeof(DNA2RunInfoDisplay)))
{
DNA2RunInfoDisplay data = (DNA2RunInfoDisplay) e.Data.GetData(typeof(DNA2RunInfoDisplay));
ListViewItem item = VisualTreeHelperUtils.FindParent<ListViewItem>((DependencyObject) e.OriginalSource);
if (item != null)
{
this.DNA2RunSetupVM.ChangeRunPriority(data, item.Content as DNA2RunInfoDisplay);
this.PropertyChanged(this, new PropertyChangedEventArgs("RunSetupInfoList"));
}
}
}
finally
{
if (this.m_DragAdorner != null)
{
this.m_DragAdorner.Visibility = Visibility.Collapsed;
}
}
}

Related

C# how to trigger an alert when all picturebox has a value

I'm creating a memory game for my schoolproject and i have a problem of triggering a messagebox when player won the game and displays a note "You hav matched all cards!". Does anyone have the solution.
One part of the code:
private void Card1_Click(object sender, EventArgs e)
{
Card1.Image = Properties.Resources.car1;
if(usedCard1 == null)
{
usedCard1 = Card1;
}
else if(usedCard1 != null && usedCard2 == null)
{
usedCard2 = Card1;
}
if(usedCard1 != null && usedCard2 != null)
{
if(usedCard1.Tag == usedCard2.Tag)
{
usedCard1 = null;
usedCard2 = null;
Card1.Enabled = false;
Dupcard1.Enabled = false;
points = Convert.ToInt32(ScoreCounter.Text);
points = points + 10;
ScoreCounter.Text = Convert.ToString(points);
}
else
{
points = Convert.ToInt32(ScoreCounter.Text);
points = points - 10;
ScoreCounter.Text = Convert.ToString(points);
timer4.Start();
}
}
}
private void Dupcard1_Click(object sender, EventArgs e)
{
Dupcard1.Image = Properties.Resources.car1;
if (usedCard1 == null)
{
usedCard1 = Dupcard1;
}
else if (usedCard1 != null && usedCard2 == null)
{
usedCard2 = Dupcard1;
}
if (usedCard1 != null && usedCard2 != null)
{
if (usedCard1.Tag == usedCard2.Tag)
{
usedCard1 = null;
usedCard2 = null;
Card1.Enabled = false;
Dupcard1.Enabled = false;
points = Convert.ToInt32(ScoreCounter.Text);
points = points + 10;
ScoreCounter.Text = Convert.ToString(points);
}
else
{
points = Convert.ToInt32(ScoreCounter.Text);
points = points - 10;
ScoreCounter.Text = Convert.ToString(points);
timer4.Start();
}
}
}
private void Win()
{
foreach(PictureBox picture in cardsHolder.Controls)
{
if(picture != null)
{
}
}
MessageBox.Show("You've matched all cards", "Congratulations");
Close();
}
PS: cardsHolder is the name of the panel, and Win is the method of triggering message when player wins the game.
I presume that you set the PictureBox.Image property to null if you don't show an image on a PictureBox. So simply check that property:
private void Win()
{
if (cardsHolder.Controls.OfType<PictureBox>().Any(pb => pb.Image == null))
return;
MessageBox.Show("You matched all the icons!", "Congratulations");
Close();
}
OfType<PictureBox> selects all PictureBoxes from the Controls collection and Any returns true if one of them has no Image.

Show Sub Menu on right Click On DataGridView - C#

Hi I added a right click event on my datagridview which shows menu but I want to show a sub menu when clicked or mouse hover on one of the menuItem
protected void datagridview1_MouseClick(object sender, MouseEventArgs e)
{
if (e.Button == MouseButtons.Right)
{
ContextMenuStrip my_menu = new ContextMenuStrip();
int position_xy_mouse_row = dataGridView1.HitTest(e.X, e.Y).RowIndex;
if (position_xy_mouse_row >= 0)
{
my_menu.Items.Add("Show Details").Name = "Details";
if ((SecurityLevel == "something" && dataGridView1.SelectedRows[0].Cells[8].Value.ToString() == "value1") || (SecurityLevel == "something" && dataGridView1.SelectedRows[0].Cells[8].Value.ToString() == "value2"))
{
my_menu.Items.Add("update").Name = "Update ";
if (dataGridView1.SelectedRows[0].Cells[8].Value.ToString() == "value1")
{
MenuItem updateStatus = new MenuItem("Update");
updateStatus.MenuItems.Add(new MenuItem("somevalue").Name = "somevalue");
updateStatus.MenuItems.Add(new MenuItem("someothervalue").Name = "someothervalue");
}
if (dataGridView1.SelectedRows[0].Cells[8].Value.ToString() == "value2")
{
MenuItem updateStatus = new MenuItem("Update");
updateStatus.MenuItems.Add(new MenuItem("someothervalue").Name = "someothervalue");
updateStatus.MenuItems.Add(new MenuItem("newvalue").Name = "newvalue");
}
}
}
my_menu.Show(dataGridView1, new Point(e.X, e.Y));
my_menu.ItemClicked += new ToolStripItemClickedEventHandler(my_menu_ItemClicked);
}
}
but I can only see 2 menuitems on my menu which are Show Details and Update, I can't see the sub menu for update.
To add sub-menu items, you need to cast the desired item to a ToolStripMenuItem, then add the sub-items to the DropDownItems property - hooking up the event handler in the constructor. You can create each with a unique event handler or just a single handler with logic checks on the ToolStripMenuItem.Name:
if (position_xy_mouse_row >= 0)
{
my_menu.Items.Add("Show Details").Name = "Details";
if ((SecurityLevel == "something" && dataGridView1.SelectedRows[0].Cells[8].Value.ToString() == "value1") || (SecurityLevel == "something" && dataGridView1.SelectedRows[0].Cells[8].Value.ToString() == "value2"))
{
my_menu.Items.Add("update").Name = "Update";
if (dataGridView1.SelectedRows[0].Cells[8].Value.ToString() == "value1")
{
(my_menu.Items["Update"] as ToolStripMenuItem).DropDownItems.Add("somevalue", null, new EventHandler(this.SubItem_Click)).Name = "somevalue";
(my_menu.Items["Update"] as ToolStripMenuItem).DropDownItems.Add("someothervalue", null, new EventHandler(this.SubItem_Click)).Name = "someothervalue";
}
if (dataGridView1.SelectedRows[0].Cells[8].Value.ToString() == "value2")
{
(my_menu.Items["Update"] as ToolStripMenuItem).DropDownItems.Add("someothervalue", null, new EventHandler(SubItem_Click)).Name = "someothervalue";
(my_menu.Items["Update"] as ToolStripMenuItem).DropDownItems.Add("newvalue", null, new EventHandler(SubItem_Click)).Name = "newvalue";
}
}
}
my_menu.Show(dataGridView1, new Point(e.X, e.Y));
my_menu.ItemClicked += new ToolStripItemClickedEventHandler(MenuItem_Clicked);
Then your handlers:
private void MenuItem_Clicked(object sender, ToolStripItemClickedEventArgs e)
{
Console.WriteLine("Clicked {0}", e.ClickedItem.Name);
}
private void SubItem_Click(object sender, EventArgs e)
{
Console.WriteLine("Clicked {0}", (sender as ToolStripMenuItem).Name);
}

DataGrid auto scrolling when doing selection

I have a custom Datagrid, in that datagrid I change the way we select element.
I have some feature added to the selection, like :
When we select element, it's like the "Ctrl" key was press.
When we click on a selected row, the row become unselected.
When we do a multiple selection, all the row change the selectedValue for the one that the first row is going to have.
When we do a multiple selection (mouse down, move, then mouse up) with Right click it's reversing the selected value of the rows.
It's a DataGrid extension, so I am coding only in C#.
For doing that I added event handle on PreviewMouseDown and MouseUp of for the datagridrow.
private enum ButtonClicked {Left, Middle, Right};
private ButtonClicked m_oMouseButtonClicked;
private void PreviewMouseDownHandler(object sender, MouseButtonEventArgs e)
{
DataGridRow row = sender as DataGridRow;
if (e.LeftButton == MouseButtonState.Pressed)
{
row.IsSelected = !row.IsSelected;
m_oMouseButtonClicked = ButtonClicked.Left;
}
else if (e.RightButton == MouseButtonState.Pressed)
{
//row.IsSelected = !row.IsSelected;
m_oMouseButtonClicked = ButtonClicked.Right;
}
row.CaptureMouse();
row.MouseMove += row_MouseMove;
e.Handled = true;
}
void row_MouseMove(object sender, MouseEventArgs e)
{
Point oPosFromThis = e.GetPosition(this);
if (oPosFromThis.Y > this.ActualHeight)
{
}
else if (oPosFromThis.Y < 0)
{
}
}
void Row_MouseUp(object sender, MouseButtonEventArgs e)
{
int nStart;
int nEnd;
DataGridRow row = sender as DataGridRow;
row.ReleaseMouseCapture();
row.MouseMove -= row_MouseMove;
int nStartRowIndex = ItemContainerGenerator.IndexFromContainer(row);
Point oPosFromRow = e.MouseDevice.GetPosition(row);
int nEndRowIndex = nStartRowIndex + (int)Math.Floor(oPosFromRow.Y / row.ActualHeight);
if (nStartRowIndex < nEndRowIndex)
{
nStart = Math.Max(nStartRowIndex, 0);
nEnd = Math.Min(nEndRowIndex, Items.Count - 1);
}
else
{
nStart = Math.Max(nEndRowIndex, 0);
nEnd = Math.Min(nStartRowIndex, Items.Count - 1);
}
for (; nStart <= nEnd; ++nStart)
{
DataGridRow oTmp = ((DataGridRow)ItemContainerGenerator.ContainerFromIndex(nStart));
if (m_oMouseButtonClicked == ButtonClicked.Left)
{
oTmp.IsSelected = row.IsSelected;
}
else if (m_oMouseButtonClicked == ButtonClicked.Right)
{
oTmp.IsSelected = !oTmp.IsSelected;
}
}
e.Handled = true;
}
I give the mouse capture to my row i clicked, to be able to catch the mouseUp even if i go outside the datagrid.
But with my code, I lost a feature that i would like to have. The auto scrolling when I do a multiple selection and i go under or upper the datagrid. I know that iI will have to add MouseMove Handler to do it, but for now i am stuck cause I don't know how to do it.
I finally found a solution by try-error attempts. I added method to get the scrollviewer element, then i am starting a Timer to execute the scroll alone.
public claa AAA
{
private enum ButtonClicked {Left, Middle, Right};
private ButtonClicked m_oMouseButtonClicked;
private DispatcherTimer m_oTimer;
private double m_nScrollOffset;
private ScrollViewer m_oScrollBar;
public IcuAlertGrid()
{
this.Initialized += IcuAlertGrid_Initialized;
this.Loaded += IcuAlertGrid_Loaded;
m_oTimer = new DispatcherTimer();
m_oTimer.Tick += m_oTimer_Tick;
m_oTimer.Interval = new TimeSpan(2500000);
}
void IcuAlertGrid_Initialized(object sender, EventArgs e)
{
setStyle0(true);
//throw new NotImplementedException();
}
void IcuAlertGrid_Loaded(object sender, RoutedEventArgs e)
{
m_oScrollBar = GetScrollViewer(this);
}
void m_oTimer_Tick(object sender, EventArgs e)
{
if (m_oScrollBar != null)
{
m_oScrollBar.ScrollToVerticalOffset(m_oScrollBar.VerticalOffset + m_nScrollOffset);
}
}
private void PreviewMouseDownHandler(object sender, MouseButtonEventArgs e)
{
DataGridRow row = sender as DataGridRow;
if (e.LeftButton == MouseButtonState.Pressed)
{
row.IsSelected = !row.IsSelected;
m_oMouseButtonClicked = ButtonClicked.Left;
}
else if (e.RightButton == MouseButtonState.Pressed)
{
//row.IsSelected = !row.IsSelected;
m_oMouseButtonClicked = ButtonClicked.Right;
}
row.CaptureMouse();
row.MouseMove += row_MouseMove;
e.Handled = true;
}
private void row_MouseMove(object sender, MouseEventArgs e)
{
DataGridRow oRow = sender as DataGridRow;
Point oPosFromThis = e.GetPosition(this);
if (oPosFromThis.Y < 0)
{
m_nScrollOffset = -1.0;
m_oTimer.Start();
}
else if (this.ActualHeight < oPosFromThis.Y)
{
m_nScrollOffset = 1.0;
m_oTimer.Start();
}
else
{
m_oTimer.Stop();
}
}
private void Row_MouseUp(object sender, MouseButtonEventArgs e)
{
int nStart;
int nEnd;
m_oTimer.Stop();
DataGridRow row = sender as DataGridRow;
row.ReleaseMouseCapture();
row.MouseMove -= row_MouseMove;
int nStartRowIndex = ItemContainerGenerator.IndexFromContainer(row);
Point oPosFromRow = e.MouseDevice.GetPosition(row);
int nEndRowIndex = nStartRowIndex + (int)Math.Floor(oPosFromRow.Y / row.ActualHeight);
if (nStartRowIndex < nEndRowIndex)
{
nStart = Math.Max(nStartRowIndex, 0);
nEnd = Math.Min(nEndRowIndex, Items.Count - 1);
}
else
{
nStart = Math.Max(nEndRowIndex, 0);
nEnd = Math.Min(nStartRowIndex, Items.Count - 1);
}
for (; nStart <= nEnd; ++nStart)
{
DataGridRow oTmp = ((DataGridRow)ItemContainerGenerator.ContainerFromIndex(nStart));
if (m_oMouseButtonClicked == ButtonClicked.Left)
{
oTmp.IsSelected = row.IsSelected;
}
else if (m_oMouseButtonClicked == ButtonClicked.Right)
{
oTmp.IsSelected = !oTmp.IsSelected;
}
}
e.Handled = true;
}
private static ScrollViewer GetScrollViewer(DependencyObject p_oParent)
{
ScrollViewer child = default(ScrollViewer);
int numVisuals = VisualTreeHelper.GetChildrenCount(p_oParent);
for (int i = 0; i < numVisuals; i++)
{
Visual v = (Visual)VisualTreeHelper.GetChild(p_oParent, i);
child = v as ScrollViewer;
if (child == null)
{
child = GetScrollViewer(v);
}
if (child != null)
{
break;
}
}
return child;
}
}

How to change the colors of the winforms treeview after SetWindowTheme has been applied

I have a windows forms treeview. The default plus minus icons of the treeview are not updated with the Windows 7 styles.
To achieve that I have used the SetWindowTheme from UXTheme.dll
SetWindowTheme(tvwRoot.Handle, "explorer", null);
After applying this, I am unable to change the selectednode color of the treeview.
I tried the following,
private void tvwRoot_MouseDown(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (tvwRoot.GetNodeAt(e.Location) != null)
{
tvwRoot.SelectedNode = tvwRoot.GetNodeAt(e.Location);
tvwRoot.SelectedNode.BackColor = System.Drawing.Color.FromArgb(51, 153, 255);
tvwRoot.SelectedNode.ForeColor = System.Drawing.Color.White;
if (e.Button == MouseButtons.Right)
{
nodRightClick = tvwRoot.SelectedNode;
blnRightClick = true;
pntLocation = e.Location;
}
}
else
{
tvwRoot.SelectedNode = null;
nodRightClick = null;
}
}
private void tvwRoot_MouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (tvwRoot.SelectedNode != null)
{
if (tnPreviousSelected != null && !tnPreviousSelected.FullPath.Equals(tvwRoot.SelectedNode.FullPath))
tnPreviousSelected = tvwRoot.SelectedNode;
else if (tnPreviousSelected == null)
tnPreviousSelected = tvwRoot.SelectedNode;
tvwRoot.SelectedNode.BackColor = System.Drawing.Color.FromArgb(51, 153, 255);
tvwRoot.SelectedNode.ForeColor = System.Drawing.Color.White;
}
}
private void tvwRoot_AfterSelect(object sender, TreeViewEventArgs e)
{
if (tnPreviousSelected != null && !tnPreviousSelected.FullPath.Equals(tvwRoot.SelectedNode.FullPath))
{
tnPreviousSelected.BackColor = tvwRoot.BackColor;
tnPreviousSelected.ForeColor = tvwRoot.ForeColor;
tnPreviousSelected = null;
}
if (tvwRoot.SelectedNode != null)
{
if (tnPreviousSelected != null && !tnPreviousSelected.FullPath.Equals(tvwRoot.SelectedNode.FullPath))
tnPreviousSelected = tvwRoot.SelectedNode;
else if (tnPreviousSelected == null)
tnPreviousSelected = tvwRoot.SelectedNode;
tvwRoot.SelectedNode.BackColor = System.Drawing.Color.FromArgb(51, 153, 255);
tvwRoot.SelectedNode.ForeColor = System.Drawing.Color.White;
}
}
But with this the color appears on the treeview after the focus is removed from the treeview.
Is there any way to change the color after SetWindow theme has been applied?

Memory leak in Windows 8.1

I've built my own control to mimic the VariableSizedGridView in Windows 8. Because that control does not support UI virtualization, I rebuilt it with virtualization. The control basically measures all the elements and calculates their positions, but only draws those that are in view. This makes for an enormous performance boost on the Surface RT.
There is one problem though, the control leaks memory. I'm sure that it's the control (or something related to it), as I've been able to reproduce the leak in an isolated app. The source code of the control is split in two classes. The VirtualizedList class is the base of the control, and defines a couple of DependencyProperties. The VirtualizedVariableSizedWrapGrid class is where the magic happens and where the items are being drawn on the screen.
I'm not sure how I can fix this issue, as it's been happening for months now, and nothing I did helped. I checked my events, tried disposing the UI elements (which is unpossible, it seems). I guess the leak happens because some child elements of the DataTemplate are still bound to the data object, and thus still reference to them, and that's why the UI objects still stay in memory. I could be completely wrong though. As you can see in the code, when I update the view, I commented out RemoveChild(old);. That's because when I reuse old FrameworkElements (created from the DataTemplate), the leak goes slower. When I recreate new items all the time, the leak is about 5MB per scroll operation.
Any help on this would be very much appreciated! Thank you.
PS: Seems like I can not attach all source code. The VirtualizedList class only defines some DependencyProperties, so I'll leave that one out.
Source
VirtualizedVariableSizedWrapGrid
[TemplatePart(Name="Root", Type=typeof(Grid))]
[TemplatePart(Name="Scroll", Type=typeof(ScrollViewer))]
[TemplatePart(Name="LayoutArea", Type=typeof(Grid))]
[TemplatePart(Name="SnappedView", Type=typeof(ListView))]
public class VirtualizedVariableSizedWrapGrid : VirtualizedList
{
public static readonly DependencyProperty SnappedItemContainerStyleProperty = DependencyProperty.Register("SnappedItemContainerStyle", typeof(Style), typeof(VirtualizedVariableSizedWrapGrid), new PropertyMetadata(null, SnappedItemContainerStyleChanged));
public static readonly DependencyProperty ListStateProperty = DependencyProperty.Register("ListState", typeof(ViewState), typeof(VirtualizedVariableSizedWrapGrid), new PropertyMetadata(ViewState.Full, ListStateChanged));
private readonly List<object> _currentDataView;
private Grid _root;
private Panel _panel;
private ScrollViewer _scrollViewer;
private ListView _snappedView;
private const double COLUMNS_PRELOADED = 2;
private const double CARD_MARGIN = 6.0;
private int _maxRows = 0;
private object _selectedItem;
private bool _moreDataRequested = false;
public delegate void CalculatingItemSizeEventHandler(ItemContainer item);
public event CalculatingItemSizeEventHandler OnCalculatingItemSize;
public event SelectionChangedEventHandler SelectionChanged;
public event EventHandler DataRequested;
public enum ViewState
{
Full,
Snapped
}
public VirtualizedVariableSizedWrapGrid()
{
_currentDataView = new List<object>();
DefaultStyleKey = typeof(VirtualizedVariableSizedWrapGrid);
this.Style = (Style) XamlReader.Load(
#"<Style xmlns=""http://schemas.microsoft.com/winfx/2006/xaml/presentation"" xmlns:x=""http://schemas.microsoft.com/winfx/2006/xaml"" xmlns:controls=""using:MeTweets.Controls"" TargetType=""controls:VirtualizedVariableSizedWrapGrid"">
<Setter Property=""Template"">
<Setter.Value>
<ControlTemplate TargetType=""controls:VirtualizedVariableSizedWrapGrid"">
<Grid x:Name=""Root"" VerticalAlignment=""Stretch"" HorizontalAlignment=""Stretch"">
<ScrollViewer x:Name=""Scroll"" ZoomMode=""Disabled"" HorizontalScrollMode=""Auto"" VerticalScrollMode=""Disabled"" HorizontalScrollBarVisibility=""Hidden"" VerticalScrollBarVisibility=""Hidden"" HorizontalAlignment=""Stretch"" VerticalAlignment=""Stretch"">
<Grid x:Name=""LayoutArea"" />
</ScrollViewer>
<ListView x:Name=""SnappedView"" HorizontalContentAlignment=""Stretch"" HorizontalAlignment=""Stretch"" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>");
this.Loaded += VirtualizedVariableSizedWrapGrid_Loaded;
}
~VirtualizedVariableSizedWrapGrid()
{
this.Loaded -= VirtualizedVariableSizedWrapGrid_Loaded;
}
#region Dependency Property Changed
private static void SnappedItemContainerStyleChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
VirtualizedVariableSizedWrapGrid varSizeGrid = sender as VirtualizedVariableSizedWrapGrid;
if (varSizeGrid == null || !(e.NewValue is Style))
return;
varSizeGrid.SetupSnappedView();
}
private static void ListStateChanged(DependencyObject sender, DependencyPropertyChangedEventArgs e)
{
VirtualizedVariableSizedWrapGrid varSizeGrid = sender as VirtualizedVariableSizedWrapGrid;
if (varSizeGrid == null || e.NewValue.Equals(e.OldValue))
return;
if (varSizeGrid.ListState == ViewState.Full)
{
varSizeGrid._scrollViewer.Visibility = Visibility.Visible;
varSizeGrid._snappedView.Visibility = Visibility.Collapsed;
}
else if (varSizeGrid.ListState == ViewState.Snapped)
{
varSizeGrid._scrollViewer.Visibility = Visibility.Collapsed;
varSizeGrid._snappedView.Visibility = Visibility.Visible;
}
if (varSizeGrid.ListState == ViewState.Full)
{
var snapScroll = varSizeGrid._snappedView.FindFirstChildOfType<ScrollViewer>();
if (snapScroll != null)
{
int index = (int)snapScroll.VerticalOffset;
if (index >= 0 && index < varSizeGrid.ItemsSource.Count)
varSizeGrid.BringIntoView(varSizeGrid.ItemsSource[index]);
}
}
else if (varSizeGrid.ListState == ViewState.Snapped)
{
if (varSizeGrid._itemContainer == null)
return;
var item = (from a in varSizeGrid._itemContainer
where (a.Column * varSizeGrid.ItemWidth) + varSizeGrid.ItemWidth > varSizeGrid._scrollViewer.HorizontalOffset + varSizeGrid.Padding.Left
select a).FirstOrDefault();
if (item == null)
return;
varSizeGrid.BringIntoView(varSizeGrid.ItemsSource[item.Index]);
}
}
#endregion
#region Virtual Voids
protected override void OnItemTemplateChanged(DependencyPropertyChangedEventArgs e)
{
Debug.WriteLine("Item template changed");
SetupSnappedView();
GenerateItemContainers();
}
protected override void OnItemsSourceChanged(DependencyPropertyChangedEventArgs e)
{
Debug.WriteLine("Items source changed");
SetupSnappedView();
if (e.OldValue != null)
{
if (e.OldValue is INotifyCollectionChanged)
{
INotifyCollectionChanged collection = (INotifyCollectionChanged)e.OldValue;
collection.CollectionChanged -= collection_CollectionChanged;
}
ClearItems();
}
if (e.NewValue != null)
{
GenerateItemContainers();
UpdateView();
if (e.NewValue is INotifyCollectionChanged)
{
INotifyCollectionChanged collection = (INotifyCollectionChanged)e.NewValue;
collection.CollectionChanged += collection_CollectionChanged;
}
}
}
protected virtual DataTemplate GetDataTemplateForItem(object item)
{
return ItemTemplate;
}
#endregion
#region Properties
public Style SnappedItemContainerStyle
{
get { return (Style)GetValue(SnappedItemContainerStyleProperty); }
set { SetValue(SnappedItemContainerStyleProperty, value); }
}
public ViewState ListState
{
get { return (ViewState)GetValue(ListStateProperty); }
set { SetValue(ListStateProperty, value); }
}
public object SelectedValue
{
get { return _selectedItem; }
set
{
if (value == _selectedItem)
return;
if (value == null)
{
_selectedItem = null;
return;
}
var oldValue = _selectedItem;
if (BringIntoView(value))
{
_selectedItem = value;
if (SelectionChanged != null)
SelectionChanged(this, new SelectionChangedEventArgs(new List<object>() { oldValue }, new List<object>() { value }));
}
}
}
#endregion
#region Overrides
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
Debug.WriteLine("OnApplyTemplate");
_root = this.GetTemplateChild("Root") as Grid;
_panel = this.GetTemplateChild("LayoutArea") as Panel;
_scrollViewer = this.GetTemplateChild("Scroll") as ScrollViewer;
_snappedView = this.GetTemplateChild("SnappedView") as ListView;
_snappedView.Loaded += _snappedView_Loaded;
_scrollViewer.ViewChanging += _scrollViewer_ViewChanging;
_scrollViewer.ViewChanged += _scrollViewer_ViewChanged;
_panel.SizeChanged += _panel_SizeChanged;
_snappedView.SelectionChanged += _snappedView_SelectionChanged;
App.RootFrame.SizeChanged += RootFrame_SizeChanged;
if (ItemsSource != null)
{
GenerateItemContainers();
UpdateView();
}
SetupSnappedView();
}
#endregion
#region Private voids
protected override void ClearItems()
{
if (_panel == null)
return;
foreach (var item in _panel.Children.Cast<FrameworkElement>())
{
RemoveChild(item);
}
_currentDataView.Clear();
_panel.Children.Clear();
}
protected override void GenerateItemContainers()
{
if (_panel == null || _panel.Visibility == Visibility.Collapsed || _panel.ActualHeight == 0 || _panel.ActualWidth == 0)
return;
_itemContainer.Clear();
if (ItemsSource == null)
return;
int _currentRow = 0, _currentColumn = 0;
int _currentColWidth = 1;
_maxRows = (int)((_panel.ActualHeight-this.Padding.Bottom-this.Padding.Top) / this.ItemHeight);
for (int ix = 0; ix < ItemsSource.Count; ix++)
{
var item = ItemsSource[ix];
var container = new ItemContainer { Index = ix };
if (_currentDataView.Contains(item))
container.IsRealized = true;
if (OnCalculatingItemSize != null)
OnCalculatingItemSize(container);
if (container.RowSpan < 0)
container.RowSpan = 0;
if (container.ColumnSpan < 0)
container.ColumnSpan = 0;
container.Column = _currentColumn;
container.Row = _currentRow;
if (container.RowSpan + _currentRow > _maxRows) //Not enough rows --> new column
{
if (_itemContainer.Count > 0)
{
// Equally split the rest of the space in this column over the elements that are currently in it
var additionalrows = _maxRows - _currentRow;
var c = _itemContainer.Where(x => x.Column == _currentColumn).ToList();
var ccount = c.Count();
var i = 0;
foreach (var t in c)
{
t.Row += (additionalrows/ccount)*i;
t.RowSpan += additionalrows/ccount;
i++;
}
// Couldn't equally divide, give the rest of the space to the last element
if (additionalrows%ccount > 0)
{
c.Last().RowSpan += additionalrows%ccount;
}
}
_currentColumn++;
container.Column = _currentColumn;
_currentRow = 0;
container.Row = _currentRow;
_currentColWidth = container.ColumnSpan;
_itemContainer.Add(container);
_currentRow += container.RowSpan;
continue;
}
//Make column as wide as widest element
if (container.ColumnSpan > _currentColWidth)
_currentColWidth = container.ColumnSpan;
if (_currentColWidth > container.ColumnSpan)
container.ColumnSpan = _currentColWidth;
_currentRow += container.RowSpan;
if (_currentRow >= _maxRows)
{
//Make sure all elements in column are as wide as widest element
foreach (var wider in
_itemContainer.Where(x => x.ColumnSpan < _currentColWidth && x.Column == _currentColumn))
{
wider.ColumnSpan = _currentColWidth;
}
_currentRow = 0;
_currentColumn += _currentColWidth;
_currentColWidth = 1;
}
_itemContainer.Add(container);
}
}
protected override void UpdateView()
{
if (_panel == null || _scrollViewer == null || _itemContainer == null || _itemContainer.Count == 0)
return;
_panel.Width = ((_itemContainer.Last().Column + 1) * this.ItemWidth) + this.Padding.Left + this.Padding.Right;
var margin = this.ItemWidth * COLUMNS_PRELOADED;
double minLeft = (_scrollViewer.HorizontalOffset - margin);
double maxLeft = (_scrollViewer.HorizontalOffset + _scrollViewer.ActualWidth + margin);
int minColumn = (int)(minLeft / this.ItemWidth)-1;
int maxColumn = (int)(maxLeft / this.ItemWidth)+1;
minLeft = (minColumn * this.ItemWidth) + this.Padding.Left;
maxLeft = (maxColumn * this.ItemWidth) + this.Padding.Left;
_currentDataView.Clear();
var shown = _itemContainer.Where(x => x.Column >= minColumn && x.Column <= maxColumn);
_currentDataView.AddRange(shown.Select(x => ItemsSource[x.Index]));
List<FrameworkElement> recycle = new List<FrameworkElement>();
foreach (var old in _panel.Children.Cast<FrameworkElement>().Where(x => x.Margin.Left < minLeft || x.Margin.Left > maxLeft ||
!(_currentDataView.Contains(x.DataContext))).ToList())
{
foreach (var recycled in _itemContainer.Where(x => ItemsSource[x.Index] == old.DataContext))
recycled.IsRealized = false;
//RemoveChild(old);
recycle.Add(old);
}
foreach (var item in shown)
{
FrameworkElement obj = recycle.FirstOrDefault();
double left, top;
if (item.IsRealized)
{
//Rearrange item if needed
obj = _panel.Children.FirstOrDefault(x => x is FrameworkElement && ((FrameworkElement)x).DataContext == ItemsSource[item.Index]) as FrameworkElement;
if (obj == null)
continue;
obj.Height = (this.ItemHeight * item.RowSpan) - (2 * CARD_MARGIN);
obj.Width = (this.ItemWidth * item.ColumnSpan) - (2 * CARD_MARGIN);
left = (item.Column * this.ItemWidth) + this.Padding.Left;
top = (item.Row * this.ItemHeight) + this.Padding.Top;
obj.Margin = new Thickness(left, top, 0, 0);
continue;
}
item.IsRealized = true;
if (obj == null)
{
obj = this.GetDataTemplateForItem(item).LoadContent() as FrameworkElement;
obj.Tapped += Item_Tapped;
obj.PointerReleased += Item_PointerReleased;
obj.PointerEntered += Item_PointerEntered;
obj.PointerExited += Item_PointerExited;
_panel.Children.Add(obj);
}
else
recycle.Remove(obj);
obj.DataContext = null;
obj.DataContext = ItemsSource[item.Index];
obj.Height = (this.ItemHeight * item.RowSpan) - (2 * CARD_MARGIN);
obj.Width = (this.ItemWidth * item.ColumnSpan) - (2 * CARD_MARGIN);
obj.VerticalAlignment = VerticalAlignment.Top;
obj.HorizontalAlignment = HorizontalAlignment.Left;
obj.Visibility = Visibility.Visible;
left = (item.Column * this.ItemWidth) + this.Padding.Left;
top = (item.Row * this.ItemHeight) + this.Padding.Top;
obj.Margin = new Thickness(left, top, 0, 0);
}
foreach (var notRecycled in recycle) //Remove not recycled items
RemoveChild(notRecycled);
Debug.WriteLine("Children count "+_panel.Children.Count);
}
private void RemoveChild(FrameworkElement item)
{
item.Tapped -= Item_Tapped;
item.PointerReleased -= Item_PointerReleased;
item.PointerEntered -= Item_PointerEntered;
item.PointerExited -= Item_PointerExited;
_panel.Children.Remove(item);
item.DataContext = null;
item.ClearValue(DataContextProperty);
}
public static IEnumerable<PropertyInfo> GetAllProperties(TypeInfo type)
{
var list = type.DeclaredProperties.ToList();
var subtype = type.BaseType;
if (subtype != null)
list.AddRange(GetAllProperties(subtype.GetTypeInfo()));
return list.ToArray();
}
public List<DependencyObject> AllChildren(DependencyObject parent)
{
var list = new List<DependencyObject>();
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(parent); i++)
{
var child = VisualTreeHelper.GetChild(parent, i);
if (child != null)
list.Add(child);
list.AddRange(AllChildren(child));
}
return list;
}
private void SetupSnappedView()
{
if (_snappedView == null)
return;
_snappedView.ItemTemplate = this.ItemTemplate;
_snappedView.ItemContainerStyle = this.SnappedItemContainerStyle;
_snappedView.ItemsSource = this.ItemsSource;
var snapScroll = this._snappedView.FindFirstChildOfType<ScrollViewer>();
if (snapScroll != null)
{
snapScroll.ViewChanged -= snapped_ViewChanged;
snapScroll.ViewChanged += snapped_ViewChanged;
}
}
private void Item_PointerExited(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
}
private void Item_PointerEntered(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
}
private bool _pointerPressed = false;
private object _pointerOriginalSource = null;
private void Item_PointerReleased(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
if (e.Handled)
return;
_pointerPressed = true;
_pointerOriginalSource = e.OriginalSource;
}
private void Item_Tapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
if (!_pointerPressed || e.OriginalSource != _pointerOriginalSource)
{
_pointerPressed = false;
return;
}
object previousObject = _selectedItem;
object dataObject = ((FrameworkElement)sender).DataContext;
if (dataObject != _selectedItem)
{
_selectedItem = dataObject;
if (SelectionChanged != null)
SelectionChanged(this, new SelectionChangedEventArgs(new List<object>() { previousObject }, new List<object>() { dataObject }));
}
_pointerPressed = false;
}
void collection_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
object item = null;
if (_itemContainer != null && _itemContainer.Count > 0 && ListState == ViewState.Snapped)
{
var snapScroll = _snappedView.FindFirstChildOfType<ScrollViewer>();
if (snapScroll != null)
{
int index = (int)snapScroll.VerticalOffset;
if (index >= 0 && index < ItemsSource.Count)
item = ItemsSource[index];
}
}
else if (_itemContainer != null && _itemContainer.Count > 0 && ListState == ViewState.Full)
{
var i = (from a in _itemContainer
where (a.Column * ItemWidth) + ItemWidth > _scrollViewer.HorizontalOffset + Padding.Left
select a).FirstOrDefault();
if (i == null)
return;
item = ItemsSource[i.Index];
}
if (e.Action == NotifyCollectionChangedAction.Add || e.Action == NotifyCollectionChangedAction.Reset)
_moreDataRequested = false;
GenerateItemContainers();
UpdateView();
//if (item != null)
// BringIntoView(item);
//else if (this.ItemsSource is IList && (this.ItemsSource as IList).Count > 0)
// BringIntoView((this.ItemsSource as IList)[0]);
}
void VirtualizedVariableSizedWrapGrid_Loaded(object sender, RoutedEventArgs e)
{
if (this.ListState == ViewState.Full)
{
this._scrollViewer.Visibility = Visibility.Visible;
this._snappedView.Visibility = Visibility.Collapsed;
}
else if (this.ListState == ViewState.Snapped)
{
this._scrollViewer.Visibility = Visibility.Collapsed;
this._snappedView.Visibility = Visibility.Visible;
}
Debug.WriteLine("VirtualizedVariableSizedWrapGrid Loaded");
if (this.ItemsSource != null && (_itemContainer == null || _itemContainer.Count == 0))
{
GenerateItemContainers();
UpdateView();
}
}
void snapped_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
if (!(sender is ScrollViewer))
return;
var scroll = (sender as ScrollViewer);
var maxOffset = scroll.ExtentHeight - scroll.ViewportHeight;
if (!_moreDataRequested && (maxOffset <= 0 || scroll.VerticalOffset >= maxOffset))
{
_moreDataRequested = true;
if (DataRequested != null)
DataRequested(this, EventArgs.Empty);
}
}
void _snappedView_Loaded(object sender, RoutedEventArgs e)
{
var snapScroll = this._snappedView.FindFirstChildOfType<ScrollViewer>();
if (snapScroll != null)
{
snapScroll.ViewChanged += snapped_ViewChanged;
}
}
private double _lastOffsetUpdate = 0;
void _scrollViewer_ViewChanging(object sender, ScrollViewerViewChangingEventArgs e)
{
if (e.NextView.HorizontalOffset == e.FinalView.HorizontalOffset)
{
UpdateView();
return;
}
if (Math.Abs(e.NextView.HorizontalOffset - _lastOffsetUpdate) > 100)
{
_lastOffsetUpdate = e.NextView.HorizontalOffset;
UpdateView();
}
}
void _scrollViewer_ViewChanged(object sender, ScrollViewerViewChangedEventArgs e)
{
if (!_moreDataRequested && this._scrollViewer.HorizontalOffset + this._scrollViewer.ActualWidth >= (this._panel.ActualWidth))
{
_moreDataRequested = true;
if (DataRequested != null)
DataRequested(this, EventArgs.Empty);
}
}
void _panel_SizeChanged(object sender, SizeChangedEventArgs e)
{
int currentMaxRows = _maxRows;
_maxRows = (int)((_panel.ActualHeight - this.Padding.Bottom - this.Padding.Top) / this.ItemHeight);
if (_maxRows != currentMaxRows) //Orientation probably changed, control got higher
{
Debug.WriteLine("Panel size changed");
ClearItems();
GenerateItemContainers();
UpdateView();
}
}
void _snappedView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count > 0)
this.SelectedValue = e.AddedItems[0];
_snappedView.SelectedItem = null;
}
void RootFrame_SizeChanged(object sender, SizeChangedEventArgs e)
{
if (_itemContainer != null && _itemContainer.Count > 0 && _panel.ActualWidth > 0)
UpdateView();
}
#endregion
#region Public voids
public override bool BringIntoView(object obj, bool animate = true)
{
try
{
if (_itemContainer == null || _itemContainer.Count == 0)
return false;
var item = (from a in _itemContainer
where ItemsSource[a.Index] == obj
select a).FirstOrDefault();
if (item == null)
return false;
//Calculate position
double offset = (item.Column * this.ItemWidth) + CARD_MARGIN;
this._scrollViewer.ChangeView(offset, null, null, !animate);
_snappedView.ScrollIntoView(obj, ScrollIntoViewAlignment.Leading);
UpdateView();
return true;
}
catch { return false; }
}
#endregion
}
Do you set ContentTemplate and/or Style for containers somewhere? Or maybe another properties such as BorderBrush etc? Maybe you do that in xaml?
If you do, try to set all these properties to null when releasing the container. It helped me in some memory leak cases.

Categories