Custom sorting and column resize does not work.
Implemented custom sorting on MouseUp event handler however
if ( hitInfo.InColumnPanel && hitInfo.HitTest == GridHitTest.ColumnEdge)
{
(e as DXMouseEventArgs).Handled = true;
return;
}
does not work for the event.
Would like to be able to click on the column header to sort and resize by dragging column edge.
private void OnMouseDown(object sender, MouseEventArgs e)
{
GridHitInfo hitInfo = gridView1.CalcHitInfo(e.Location);
if (hitInfo.HitTest == GridHitTest.ColumnEdge)
{
isEdgeClicked = true;
}
}
private void OnMouseUp(object sender, System.Windows.Forms.MouseEventArgs e)
{
if (isEdgeClicked)
{ isEdgeClicked = false;
return;
}
else
{
(e as DXMouseEventArgs).Handled = true;
}
}
Related
I have an WPF app using MVVM that shows a log in a ListView control. I have it bound to an ObservableCollection and the control updates when items are added.
I have it coded so that when it starts, it automatically scrolls to the top when an item is inserted into the collection at position 0 so it always shows the latest log message. This works on all machines I have tested.
When a user does something on the ListView (clicks or scrolls), the automatic scrolling is turned off so the user can look at any part of the log they want. When they are finished looking at the log, they can click a button to turn the automatic scrolling back on. Everything works except on one of my test machines, the view changes as items are added. On my dev machine and another test machine, the ListView window does not change when things are added to the collection. Same code/config files are used for all systems.
For example:
The user scrolls to show "My Item" at the top of the ListView.
Another log message is added.
I want "My Item" to still show at the top of the ListView.
Dev machine and one Test machine: "My Item" shows at the top of the ListView.
Another Test Machine: "My Item" is now in the second row of the ListView.
The original change request was because this scrolling was not working on some machines but not others. After much time, there seems to be a difference in the machines themselves that is effecting this.
Is there some system setting that would control this?
XAML:
<ListView Grid.Row="1" Grid.Column="9" Name="messagesListView"
Grid.ColumnSpan="3" Margin="8,0,40,0"
ItemsSource="{Binding StatusMessagesList}"
SelectionChanged="messagesListView_SelectionChanged"
PreviewMouseWheel="messagesListView_PreviewMouseWheel"
MouseDoubleClick="batchesListView_MouseDoubleClick"
PreviewMouseDown="messagesListView_MouseDown"
HorizontalAlignment="Stretch">
</ListView>
Code Behind:
private void ScrollToTop()
{
scrollPos = 0;
ScrollSpot.Text = scrollPos.ToString();
ScrollToPos();
}
private void ScrollToPos()
{
ScrollViewer scrollViewer = GetScrollViewer(messagesListView) as ScrollViewer;
if (scrollViewer != null && _viewState)
scrollViewer.ScrollToVerticalOffset(scrollPos);
}
private void autoScrollButton_Click(object sender, RoutedEventArgs e)
{
messagesListView.SelectedItem = null;
autoScrollButton.Visibility = Visibility.Hidden;
_viewState = true;
ScrollToTop();
}
private void ListBox_CollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
{
if (e.NewItems != null && e.NewItems.Count > 0)
{
ScrollViewer scrollViewer = GetScrollViewer(messagesListView) as ScrollViewer;
if (scrollViewer != null && _viewState)
{
ScrollToTop();
}
if(scrollViewer != null && !_viewState)
{
scrollPos += e.NewItems.Count;
ScrollSpot.Text = scrollPos.ToString();
ScrollToPos();
}
}
}
private void messagesListView_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
_viewState = false;
autoScrollButton.Visibility = Visibility.Visible;
}
private void messagesListView_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
_viewState = false;
autoScrollButton.Visibility = Visibility.Visible;
}
private void messagesListView_Scroll(object sender, System.Windows.Controls.Primitives.ScrollEventArgs e)
{
_viewState = false;
autoScrollButton.Visibility = Visibility.Visible;
}
private void messagesListView_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource.GetType().ToString().IndexOf("Rectangle") >= 0)
{
_viewState = false;
autoScrollButton.Visibility = Visibility.Visible;
}
}
Code to Add to Collection:
{
if (_statusMessagesList == null)
StatusMessagesList = new ObservableCollection<string>();
string stMsg = string.Format("{0} {1} {2}", DateTime.Now.ToShortDateString(), DateTime.Now.ToShortTimeString(), message);
StatusMessagesList.Insert(0, stMsg);
Thanks,
Brad P.
Update: I never found out why one system worked and the other did not. However, the solution I found that worked on both was to set messagesListView.CanContentScroll = False
and then manually keep track of the Offset Position on the ScrollViewer:
{
SetUpManualScroll(0);
}
private void messagesListView_PreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
double scrollAmt = (e.Delta / 120) * -48;
SetUpManualScroll(scrollAmt);
}
private void messagesListView_Scroll(object sender, System.Windows.Controls.Primitives.ScrollEventArgs e)
{
SetUpManualScroll(e.NewValue);
}
private void messagesListView_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
SetUpManualScroll(0);
}
private void messagesListView_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
if (e.OriginalSource.GetType().ToString().IndexOf("TextBlock") < 0 && e.OriginalSource.GetType().ToString().IndexOf("Border") < 0)
{
if (_scrollviewer.VerticalOffset != 0)
SetUpManualScroll(0);
else
{
messagesListView.SelectedItem = null;
autoScrollButton.Visibility = Visibility.Hidden;
_viewState = true;
ScrollToTop();
}
}
}
private void SetUpManualScroll(double d)
{
_viewState = false;
autoScrollButton.Visibility = Visibility.Visible;
_scrollviewer.UpdateLayout();
double newPos = _scrollviewer.VerticalOffset + d;
if (newPos < 0)
newPos = 0;
ScrollPos = newPos;
}
private void ScrollToTop()
{
ScrollPos = 0;
ScrollToPos();
}
private void ScrollToPos()
{
if (_scrollviewer == null)
{
_scrollviewer = GetScrollViewer(messagesListView);
}
_scrollviewer.UpdateLayout();
_scrollviewer.ScrollToVerticalOffset(ScrollPos);
}
Microsoft Blend allows changing numeric values of properties like Left, Top etc. through continuous drag. User clicks in the property value box, keeps the button down and drags left or right to decrease/increase the value. Simple.
The special thing about it is that if cursor reaches the left or right end of the screen and user still wants to drag more, they can continue dragging and the cursor will start over from the other end of the screen.
I'm trying to do this in one of my WPF applications using Thumb control. Using DragDetla event, if I find that the Thumb has reach the edge of the screen, I set its position to the far end. But this makes the value of e.HorizontalChange as big as the width of entire screen. How can I change Thumb's position during drag without affecting horizontal change value?
I have realized this in a WPF control by using a textbox and subscribing to events such as:
PreviewMouseDown
MouseUp and
MouseMove
MouseEnter
The drag until you reach screen limits requires a mouse capture or call to CaptureMouse method available on any UIElement. On the other side, you need to release the mouse at some point which requires a call of the ReleaseMouseCapture method. The solution could go like this:
Declare an enumeration to model the drag direction
internal enum MouseDirections
{
None,
LeftRight,
UpDown
}
Declare a class to keep trak of mouse origin (first location) and current location:
internal class MouseIncrementor
{
private MouseDirections _enumMouseDirection = MouseDirections.None;
private Point _objPoint;
private readonly Point _initialPoint;
public MouseIncrementor(Point objPoint, MouseDirections enumMouseDirection)
{
_objPoint = objPoint;
_initialPoint = _objPoint;
_enumMouseDirection = enumMouseDirection;
}
public MouseDirections MouseDirection
{
get
{
return _enumMouseDirection;
}
protected set
{
_enumMouseDirection = value;
}
}
public Point InitialPoint
{
get
{
return _initialPoint;
}
}
public Point Point
{
get
{
return _objPoint;
}
set
{
_objPoint = value;
}
}
internal MouseDirections SetMouseDirection(Point pos)
{
double deltaX = this.Point.X - pos.X;
double deltaY = this.Point.Y - pos.Y;
if (Math.Abs(deltaX) > Math.Abs(deltaY))
MouseDirection = MouseDirections.LeftRight;
else
{
if (Math.Abs(deltaX) < Math.Abs(deltaY))
MouseDirection = MouseDirections.UpDown;
}
return MouseDirection;
}
}
I have a custom control that contains a TextBox named _PART_TextBox:
TextBox _PART_TextBox;
...and field for the MouseIncrementor:
MouseIncrementor _objMouseIncr;
...these are wired up like this:
_PART_TextBox.MouseEnter += _PART_TextBox_MouseEnter;
_PART_TextBox.GotKeyboardFocus += _PART_TextBox_GotKeyboardFocus;
_PART_TextBox.LostKeyboardFocus += _PART_TextBox_LostKeyboardFocus;
_PART_TextBox.MouseMove += _PART_TextBox_MouseMove;
_PART_TextBox.MouseUp += _PART_TextBox_MouseUp;
_PART_TextBox.PreviewMouseDown += _PART_TextBox_PreviewMouseDown;
_PART_TextBox.LostMouseCapture += _PART_TextBox_LostMouseCapture;
and a number of event handlers are required to get this to work:
private void _PART_TextBox_LostMouseCapture(object sender, MouseEventArgs e)
{
_objMouseIncr = null;
}
private void _PART_TextBox_MouseUp(object sender, MouseButtonEventArgs e)
{
if (_objMouseIncr != null)
{
var mouseUpPosition = GetPositionFromThis(e);
if (_objMouseIncr.InitialPoint.Equals(mouseUpPosition))
{
_PART_TextBox.Focus();
}
}
_PART_TextBox.ReleaseMouseCapture();
_objMouseIncr = null;
}
private void _PART_TextBox_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
if (IsKeyboardFocusWithin == false)
{
_objMouseIncr = new MouseIncrementor(this.GetPositionFromThis(e), MouseDirections.None);
e.Handled = true;
}
}
private void _PART_TextBox_MouseMove(object sender, MouseEventArgs e)
{
// nothing to do here
if (_objMouseIncr == null)
return;
if (e.LeftButton != MouseButtonState.Pressed)
return;
if (CanIncreaseCommand() == false && CanDecreaseCommand() == false)
{
// since we can't parse the value, we are out of here, i.e. user put text in our number box
_objMouseIncr = null;
return;
}
var pos = GetPositionFromThis(e);
double deltaX = _objMouseIncr.Point.X - pos.X;
double deltaY = _objMouseIncr.Point.Y - pos.Y;
if (_objMouseIncr.MouseDirection == MouseDirections.None)
{
// this is our first time here, so we need to record if we are tracking x or y movements
if (_objMouseIncr.SetMouseDirection(pos) != MouseDirections.None)
_PART_TextBox.CaptureMouse();
}
if (_objMouseIncr.MouseDirection == MouseDirections.LeftRight)
{
if (deltaX > 0)
OnDecrement(LargeStepSize);
else
{
if (deltaX < 0)
OnIncrement(LargeStepSize);
}
}
else
{
if (_objMouseIncr.MouseDirection == MouseDirections.UpDown)
{
if (deltaY > 0)
{
if (CanIncreaseCommand() == true)
OnIncrease();
}
else
{
if (deltaY < 0)
{
if (CanDecreaseCommand() == true)
OnDecrease();
}
}
}
}
_objMouseIncr.Point = GetPositionFromThis(e);
}
private Point GetPositionFromThis(MouseEventArgs e)
{
return this.PointToScreen(e.GetPosition(this));
}
private void _PART_TextBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
_objMouseIncr = null;
(sender as TextBox).Cursor = Cursors.ScrollAll;
}
private void _PART_TextBox_MouseEnter(object sender, MouseEventArgs e)
{
if (IsMouseDragEnabled == false)
return;
if (IsKeyboardFocusWithin)
(sender as TextBox).Cursor = Cursors.IBeam;
else
(sender as TextBox).Cursor = Cursors.ScrollAll;
}
private void _PART_TextBox_GotKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
_objMouseIncr = null;
(sender as TextBox).Cursor = Cursors.IBeam;
}
The full project is located here: https://github.com/Dirkster99/NumericUpDownLib
Please let me know if I am missing something or if there are additional questions.
This NumericUpDown (NUD) floats over a map. When it gets visible I need to re-direct the next key-stroke inside the control overriding the current value.
With great pain I've found this solution:
private void LengthInput_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
{
if ((bool)(e.NewValue))
{
...
LengthInputBox.ShowButtons = true;
try
{
LengthInputBox.Focus();
if (m_lengthTextBox == null)
{
LengthInputBox.ApplyTemplate();
m_lengthTextBox = LengthInputBox.Template.FindName("textbox", LengthInputBox) as TextBox;
}
if (m_lengthTextBox != null)
{
m_lengthTextBox.SelectAll();
m_lengthTextBox.Focus();
}
}
finally
{
LengthInputBox.ShowButtons = false;
}
...
NUD is the LengthInputBox control. Focus method sets the focus on the NUD buttons.
Template.FindName("textbox"... retrieve the internal TextBox of NUD. If found, or previously found, it selects all and set focus on the text.
Finally, I remove the Up/Down buttons (I don't need them. Although I've done lot of variations with or without them, their presence does not change the behavior...)
It works for the first time, but on the second attempt it fails again.
Any ideas?
Select and Focus are bit slow. Using a Dispatcher has solved the issue:
private void LengthInputBox_GotFocus(object sender, RoutedEventArgs e)
{
if (m_lengthTextBox == null)
{
LengthInputBox.ApplyTemplate();
m_lengthTextBox = LengthInputBox.Template.FindName("textbox", LengthInputBox) as TextBox;
}
if (m_lengthTextBox != null)
{
m_lengthTextBox.Focusable = true;
m_lengthTextBox.IsTabStop = true;
if (!m_lengthTextBox.IsFocused)
Dispatcher.BeginInvoke(new Action(() =>
{
var dot = m_lengthTextBox.Text.IndexOf('.');
m_lengthTextBox.Select(dot, m_lengthTextBox.Text.Length - dot);
m_lengthTextBox.Focus();
}));
}
LengthInputBox.CaptureMouse();
}
(Don't forget to release the mouse:
private void LengthInput_KeyDown(object sender, KeyEventArgs e)
{
switch (e.Key)
{
case Key.Escape:
case Key.Enter:
LengthInputBox.ReleaseMouseCapture();
ViewModel.IsLengthInputVisible = false;
e.Handled = true;
break;
}
}
)
I'm trying to prevent the WPF Bing Maps control from panning when the user is dragging a pushpin. What I do is that when the user selecting the pushpin with the MouseLeftButtonDown I'm, taking over the events from the map ViewChangeStart, ViewChangeOnFrame and set the e.Handled property to true.
What I was expecting is that if I set the property to true the events are canceled and panning is disabled. However the map is still panning.
Another approach what I tried is setting the property SupportedManipulations to None. Both options don't have the expected results.
Below is the code that I'm using for my DraggablePushpin
public class DraggablePushpin : Pushpin
{
private bool isDragging = false;
protected override void OnPreviewMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
var parentLayer = this.Parent as MapLayer;
if (parentLayer != null)
{
Map parentMap = parentLayer.Tag as Map;
if (parentMap != null)
{
parentMap.ViewChangeStart += parentMap_ViewChangeStart;
parentMap.MouseLeftButtonUp += parentMap_MouseLeftButtonUp;
parentMap.MouseMove += parentMap_MouseMove;
parentMap.SupportedManipulations = System.Windows.Input.Manipulations.Manipulations2D.None;
}
}
this.isDragging = true;
base.OnPreviewMouseLeftButtonDown(e);
}
protected override void OnMouseLeftButtonDown(System.Windows.Input.MouseButtonEventArgs e)
{
base.OnMouseLeftButtonDown(e);
}
void parentMap_MouseMove(object sender, System.Windows.Input.MouseEventArgs e)
{
var map = sender as Map;
// Check if the user is currently dragging the Pushpin
if (this.isDragging)
{
// If so, the Move the Pushpin to where the Mouse is.
var mouseMapPosition = e.GetPosition(map);
var mouseGeocode = map.ViewportPointToLocation(mouseMapPosition);
this.Location = mouseGeocode;
}
}
void parentMap_MouseLeftButtonUp(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
(sender as Map).SupportedManipulations = System.Windows.Input.Manipulations.Manipulations2D.All;
}
protected override void OnMouseLeftButtonUp(System.Windows.Input.MouseButtonEventArgs e)
{
var parentLayer = this.Parent as MapLayer;
if (parentLayer != null)
{
Map parentMap = parentLayer.Tag as Map;
if (parentMap != null)
{
parentMap.SupportedManipulations = System.Windows.Input.Manipulations.Manipulations2D.All;
}
}
}
void parentMap_ViewChangeStart(object sender, MapEventArgs e)
{
if (this.isDragging)
{
e.Handled = true;
}
}
}
Hi
I'm trying to get rid of the annoying "About Silverlight" context menu that pops up whenever you right click in a Silverlight application. I've added the usual ways:
In App.xaml
rootVisual.MouseRightButtonDown += ((s, args) => args.Handled = true);
and the same for all ChildWindows.
The problem that persist is in all "pop up"-controls like comboboxes and datepicker calender popup. There I can't get rid of it. I would like to handle the right click in a style that I can make implicit for the entire application. Is this possible? Can I solve it some other smart way?
Best
Daniel
The answer was to inherit the combobox and make a custom control like this:
public class CellaComboBox : ComboBox
{
public CellaComboBox()
{
DropDownOpened += _dropDownOpened;
DropDownClosed += _dropDownClosed;
}
private static void _dropDownClosed(object sender, EventArgs e)
{
HandlePopupRightClick(sender, false);
}
private static void _dropDownOpened(object sender, EventArgs e)
{
HandlePopupRightClick(sender, true);
}
private static void HandlePopupRightClick(object sender, bool hook)
{
ComboBox box = (ComboBox)sender;
var popup = box.GetChildElement<Popup>();
if (popup != null)
{
HookPopupEvent(hook, popup);
}
}
static void HookPopupEvent(bool hook, Popup popup)
{
if (hook)
{
popup.MouseRightButtonDown += popup_MouseRightButtonDown;
popup.Child.MouseRightButtonDown += popup_MouseRightButtonDown;
}
else
{
popup.MouseRightButtonDown -= popup_MouseRightButtonDown;
popup.Child.MouseRightButtonDown -= popup_MouseRightButtonDown;
}
}
static void popup_MouseRightButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
e.Handled = true;
}
with the extension method for framworkelement looking like this:
public static class FrameworkElementExtensions
{
public static TType GetChildElement<TType>(this DependencyObject parent) where TType : DependencyObject
{
TType result = default(TType);
if (parent != null)
{
result = parent as TType;
if (result == null)
{
for (int childIndex = 0; childIndex < VisualTreeHelper.GetChildrenCount(parent); ++childIndex)
{
var child = VisualTreeHelper.GetChild(parent, childIndex) as FrameworkElement;
result = GetChildElement<TType>(child) as TType;
if (result != null) return result;
}
}
}
return result;
}
}
You need to handle the DatePicker in the same way but instead of DropDownOpened and DropDownClosed you use CalenderOpened and CalenderClosed
C# Corner has an article for fixing the about popup on Silverlight 3:
Disable Context Menu in Silverlight 3 Application