Panning not working in a FlowDocumentScrollViewer (WPF) - wpf

The bounty expires in 2 hours. Answers to this question are eligible for a +50 reputation bounty.
Simon is looking for an answer from a reputable source:
I'm looking for a solution that uses native panning instead of emulating one, like if there were images instead of paragraph elements. I don't understand how this is not possible, it seems so basic...
I have a FlowDocument inside a FlowDocumentScrollViewer. I can see the scrollbars and use them to scroll text. To enable panning using touch gestures, I set ScrollViewer.PanningMode="Both". But that only works if there is an image in the FlowDocument, and if I start the touch gesture from the image. In other words, I can pan by pressing, moving and releasing, but only if when I press, my finger touches an image. If I first press in the text, nothing happens (not able to scroll).
Here's the XAML code:
<Window x:Class="TestWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:TestWPF"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<FlowDocumentScrollViewer Height="350" IsSelectionEnabled="False" ScrollViewer.PanningMode="Both">
<FlowDocument Background="Ivory" Foreground="Black" FontSize="20">
<Section >
<Paragraph>Paragraph 0</Paragraph>
<Paragraph>Paragraph 1</Paragraph>
<Paragraph>Paragraph 2</Paragraph>
<Paragraph>Paragraph 3</Paragraph>
<Paragraph>Paragraph 4</Paragraph>
<Paragraph>Paragraph 5</Paragraph>
<Paragraph>Paragraph 6</Paragraph>
<Paragraph>Paragraph 7</Paragraph>
<Paragraph>Paragraph 8</Paragraph>
<Paragraph>Paragraph 9</Paragraph>
<Paragraph>Paragraph 10</Paragraph>
<Paragraph>Paragraph 11</Paragraph>
<Paragraph>Paragraph 12</Paragraph>
<Paragraph>Paragraph 13</Paragraph>
<Paragraph>Paragraph 14</Paragraph>
<Paragraph>Paragraph 15</Paragraph>
<Paragraph>Paragraph 16</Paragraph>
<Paragraph>Paragraph 17</Paragraph>
<Paragraph>Paragraph 18</Paragraph>
<Paragraph>Paragraph 19</Paragraph>
<Paragraph>Paragraph 20</Paragraph>
<Paragraph>Paragraph 21</Paragraph>
<Paragraph>Paragraph 22</Paragraph>
<Paragraph>Paragraph 23</Paragraph>
</Section>
</FlowDocument>
</FlowDocumentScrollViewer>
</Grid>
</Window>
Using a <TextBlock> and setting ScrollViewer.PanningMode works fine, but I need to use <FlowDocumentScrollViewer>.
It looks like <Paragraph> elements somehow trap events.
Apart from implementing a workaround (which gives poor user experience), how can we fix that?
Thank you

I think the paragraphs grab any touch down event. I don't have any touch device to test. But I cannot scroll the FlowDocumentScrollViewer with mouse inside the document.
A likely work round is to handle preview events and scroll the relevant scrollviewer by the delta moved.
Handlers here deal with both mouse and touch.
bool IsScrolling = false;
Point LastPoint;
private void FlowDocumentScrollViewer_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
HandleDown(sender);
}
private void HandleDown(object sender)
{
var sv = sender as FlowDocumentScrollViewer;
if (sender != null)
{
IsScrolling = true;
LastPoint = Mouse.GetPosition(sv);
}
}
private void FlowDocumentScrollViewer_PreviewMouseMove(object sender, MouseEventArgs e)
{
HandleMove(sender);
}
private void FlowDocumentScrollViewer_PreviewMouseUp(object sender, MouseButtonEventArgs e)
{
IsScrolling = false;
}
private void FlowDocumentScrollViewer_PreviewTouchDown(object sender, TouchEventArgs e)
{
HandleDown(sender);
}
private void FlowDocumentScrollViewer_PreviewTouchUp(object sender, TouchEventArgs e)
{
IsScrolling = false;
}
private void FlowDocumentScrollViewer_PreviewTouchMove(object sender, TouchEventArgs e)
{
HandleMove(sender);
}
private void HandleMove(object sender)
{
var fdsv = sender as FlowDocumentScrollViewer;
if (fdsv == null || !IsScrolling)
{
return;
}
var ThisPoint = Mouse.GetPosition(fdsv);
double dY = (ThisPoint.Y - LastPoint.Y);
double dX = (ThisPoint.X - LastPoint.X);
ScrollViewer sv = fdsv.GetChildOfType<ScrollViewer>();
sv.ScrollToVerticalOffset(sv.VerticalOffset - dY);
LastPoint = ThisPoint;
}
Handle those events on the FlowDocumentScrollViewer
<FlowDocumentScrollViewer Height="350"
IsSelectionEnabled="False"
ScrollViewer.PanningMode="Both"
PreviewMouseDown ="FlowDocumentScrollViewer_PreviewMouseDown"
PreviewTouchDown="FlowDocumentScrollViewer_PreviewTouchDown"
PreviewMouseUp="FlowDocumentScrollViewer_PreviewMouseUp"
PreviewTouchUp="FlowDocumentScrollViewer_PreviewTouchUp"
PreviewMouseMove="FlowDocumentScrollViewer_PreviewMouseMove"
PreviewTouchMove="FlowDocumentScrollViewer_PreviewTouchMove"
>
With these in place, I can drag and scroll with mouse.
Getchildoftype
public static class ExtensionMethods
{
public static T GetChildOfType<T>(this DependencyObject depObj) where T : DependencyObject
{
if (depObj == null) return null;
for (int i = 0; i < VisualTreeHelper.GetChildrenCount(depObj); i++)
{
var child = VisualTreeHelper.GetChild(depObj, i);
var result = (child as T) ?? GetChildOfType<T>(child);
if (result != null) return result;
}
return null;
}
}

Related

How to scale a shape by selecting its stroke in wpf

I am new to WPF I want to scale ellipse by selecting its stroke. I have set IsManipulationEnabled=true but an event not triggering. Below is my code
<Path Stretch="Fill" Stroke="Black" ManipulationDelta="Path_ManipulationDelta"
IsManipulationEnabled="True" StrokeThickness="4">
<Path.Data>
<EllipseGeometry Center="0,0" RadiusX="200" RadiusY="200"/>
</Path.Data>
</Path>
Please Help.enter image description here
Here is some code that may give you some ideas:
In this sample, I'm using some basic mouse events MouseDown, MouseMove, and MouseUp so that I can detect when a user clicks on the Path, and when they start to drag the mouse.
XAML
<Window x:Class="WpfApp4.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApp4"
Title="MainWindow"
Width="800"
Height="450"
UseLayoutRounding="True">
<Grid>
<Canvas x:Name="Canvas">
<Path x:Name="CirclePath"
MouseDown="OnMouseDown"
MouseMove="OnMouseMove"
MouseUp="OnMouseUp"
Stretch="Fill"
Stroke="Black"
StrokeThickness="4">
<Path.Data>
<EllipseGeometry x:Name="EllipseGeometry"
Center="0,0"
RadiusX="100"
RadiusY="100" />
</Path.Data>
</Path>
</Canvas>
</Grid>
</Window>
In the OnMouseDown handler, I check to see if the left mouse button is down and then I capture the mouse and get the position of the mouse relative to the Canvas.
Next, in the OnMouseMove handler, if the left button is still down - the user is dragging - I get the new mouse position and calculate the offset based on the old mouse position. Then I update the EllipseGeometry to reflect the mouse offset.
Finally, in the OnMouseUp handler, I release the mouse capture.
Code-Behind
using System.Windows;
using System.Windows.Input;
namespace WpfApp4
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private Point oldMousePosition;
public MainWindow()
{
InitializeComponent();
}
private void OnMouseDown(object sender, MouseButtonEventArgs e)
{
if(e.ChangedButton != MouseButton.Left) return;
Mouse.Capture(CirclePath);
oldMousePosition = e.GetPosition(Canvas);
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed) return;
var newMousePosition = e.GetPosition(Canvas);
var offset = newMousePosition - oldMousePosition;
EllipseGeometry.RadiusX += offset.X / 2;
EllipseGeometry.RadiusY += offset.Y / 2;
oldMousePosition = newMousePosition;
}
private void OnMouseUp(object sender, MouseButtonEventArgs e)
{
Mouse.Capture(null);
}
}
}
I hope this helps.
XAML
XAML
<Window x:Class="WidgetWpf.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WidgetWpf"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Viewbox>
<Grid Name="MainGrid">
<Ellipse x:Name="DottedCircle" Width="200" Height="200" Stroke="White" StrokeThickness="2" Opacity="0.90" StrokeDashArray="4 4"
MouseDown="DottedCircle_MouseDown"
MouseMove="DottedCircle_MouseMove"
MouseUp="DottedCircle_MouseUp"
MouseEnter="DottedCircle_MouseEnter"
MouseLeave="DottedCircle_MouseLeave"
/>
</Grid>
</Viewbox>
</Window>
//Here is my code behind
public partial class MainWindow : Window
{
#region Variables
MatrixTransform transform;
Point OldMousePosition;
Point NewMousePosition;
double[] Dimensions = new double[2];
Rect rect = new Rect();
bool IsResizeMode;
bool IsDragAndDropMode;
#endregion
public MainWindow()
{
InitializeComponent();
}
private void DottedCircle_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ChangedButton != MouseButton.Left) return;
Mouse.Capture(DottedCircle);
OldMousePosition = e.GetPosition(MainGrid);
}
private void DottedCircle_MouseMove(object sender, MouseEventArgs e)
{
DottedCircle.ToolTip = e.GetPosition(MainGrid);
if (e.LeftButton != MouseButtonState.Pressed) return;
var NewMousePosition = e.GetPosition(MainGrid);
var offset = NewMousePosition-OldMousePosition;
#region working by co-ordinate
//get center of grid
double dicisionPoint=0.0 ;
double CP_X = MainGrid.ActualWidth / 2;
double CP_Y = MainGrid.ActualHeight / 2;
//1 st co-ordinate
if(NewMousePosition.X>CP_X && NewMousePosition.Y<CP_Y)
{
dicisionPoint = offset.X;
}
//2nd cordinate
else if (NewMousePosition.X < CP_X && NewMousePosition.Y < CP_Y)
{
dicisionPoint = -offset.X;
}
else if (NewMousePosition.X < CP_X && NewMousePosition.Y > CP_Y)
{
dicisionPoint = offset.Y;
}
else if (NewMousePosition.X > CP_X && NewMousePosition.Y > CP_Y)
{
dicisionPoint = offset.Y;
}
if (DottedCircle.Width+ dicisionPoint < InnerCircle.Width)
{
DottedCircle.Fill = new SolidColorBrush(Colors.Transparent);
DottedCircle.Width += dicisionPoint;
DottedCircle.Height += dicisionPoint;
}
else if (DottedCircle.Width+ dicisionPoint>= InnerCircle.Width) { DottedCircle.Fill = new SolidColorBrush(Colors.Red); }
#endregion
OldMousePosition = NewMousePosition;
DottedCircle.ToolTip = offset.X+ "__" + offset.Y;
}
private void DottedCircle_MouseUp(object sender, MouseButtonEventArgs e)
{
Mouse.Capture(null);
DottedCircle.Style = null;
}
private void DottedCircle_MouseEnter(object sender, MouseEventArgs e)
{
DottedCircle.Stroke = new SolidColorBrush( Colors.Blue);
DottedCircle.Style = (Style)Application.Current.Resources["DiffPathStyle"];
}
private void DottedCircle_MouseLeave(object sender, MouseEventArgs e)
{
DottedCircle.Stroke = new SolidColorBrush(Colors.White);
DottedCircle.Style = null;
}
}

WPF Popup wrapping when dragging vertically

I have a project that uses a System.Windows.Controls.Primatives.Popup to drag a 'tooltip' like control along with a mouse.
Whenever the drag crosses a horizontal line the popup 'wraps' to the bottom of the screen - despite having sane values for the VerticalOffset. The point at which this wrapping occurs appears to be tied to the HEIGHT of the window, but not it's position.
Here's the code from the sandbox project I have created that also exhibits the same behavior:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.MainGrid.MouseDown += Grid_MouseDown;
this.MainGrid.MouseUp += Grid_MouseUp;
this.MainGrid.MouseMove += (s, e) => { if (this.Popup.IsOpen) { Popup_Drag(s, e); } };
this.Popup.MouseMove += Popup_Drag;
}
private void Popup_Drag(object sender, MouseEventArgs e)
{
Popup.HorizontalOffset = e.GetPosition(this.Popup).X;
Popup.VerticalOffset = e.GetPosition(this.Popup).Y;
this.Status_Top.Text = String.Format("Height/Top: {0}/{1} Width/Left: {2}/{3}", this.Height, this.Top, this.Width, this.Left);
this.Status.Text = String.Format("Vertical Offset: {0} Horizontal Offset: {1}", Popup.VerticalOffset, Popup.HorizontalOffset);
}
private void Grid_MouseUp(object sender, MouseButtonEventArgs e)
{
this.Popup.IsOpen = false;
}
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
this.Popup.IsOpen = true;
Popup_Drag(sender, e);
}
}
And the Window XAML:
<Window x:Class="WpfSandbox.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid x:Name="MainGrid" Background="Purple">
<TextBlock x:Name="Status_Top"></TextBlock>
<Popup x:Name="Popup" Cursor="Hand" HorizontalAlignment="Left"
VerticalAlignment="Bottom" IsOpen="True">
<TextBlock Background="Blue" Foreground="White">
<TextBlock x:Name="Status">TEXT</TextBlock></TextBlock>
</Popup>
</Grid>
</Window>
I was able to fix this by adding Placement="RelativePoint" to the Popup attributes. Apparently this is the default in Silverlight, but not WPF.

Set events for new UIelements on runtime

I'm kinda confused with some problem, I'm doing a project where the user should be able to design questions with radio buttons, combo box, etc (kinda like toolbox from VS10 to design your XAML).
So far I can drag and drop an UIElement that I previously created, problem comes when the user creates a new element from my toolbox, I can't find the way to make that new UIElement to get the same events from my previosly created UIElement. Take a look at the code
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Canvas Height="190" HorizontalAlignment="Left" Margin="158,41,0,0" Name="canvas1" VerticalAlignment="Top" Width="322" AllowDrop="True">
<Button Content="PROBANDO" Height="23" Name="button" Width="75" Canvas.Left="113" Canvas.Top="43" PreviewMouseDown="button_PreviewMouseDown" PreviewMouseMove="button_PreviewMouseMove" MouseUp="button_MouseUp" IsEnabled="True" />
<TextBlock Canvas.Left="99" Canvas.Top="147" Height="23" Name="textBlock" Text="" Width="107" />
</Canvas>
<ListBox Height="190" Name="listBox" Width="126" Margin="12,41,365,80" >
<ListBoxItem Content="Radio Button" Selected="radio_Selected" Name="radio" />
<ListBoxItem Content="Text" Selected="text_Selected" Name="text" />
<ListBoxItem Content="Combo Box" Name="combo" Selected="combo_Selected" />
</ListBox>
</Grid>
</Window>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
Point p;
private void button_MouseUp(object sender, MouseButtonEventArgs e)
{
button.ReleaseMouseCapture();
}
private void button_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
button.CaptureMouse();
p = e.GetPosition(canvas1);
}
private void button_PreviewMouseMove(object sender, MouseEventArgs e)
{
Point x = e.GetPosition(canvas1);
if (e.LeftButton == MouseButtonState.Pressed)
{
Canvas.SetLeft(button, Canvas.GetLeft(button) + (x.X - p.X));
Canvas.SetTop(button, Canvas.GetTop(button) + (x.Y - p.Y));
}
p = x;
}
private void generic_PreviewMouseDown(UIElement sender, MouseEventArgs e)
{
Point x = e.GetPosition(canvas1);
if (e.LeftButton == MouseButtonState.Pressed)
{
Canvas.SetLeft(sender, Canvas.GetLeft(sender) + (x.X - p.X));
Canvas.SetTop(sender, Canvas.GetTop(sender) + (x.Y - p.Y));
}
p = x;
}
private void radio_Selected(object sender, RoutedEventArgs e)
{
RadioButton newRadio = new RadioButton();
canvas1.Children.Add(newRadio);
newRadio.PreviewMouseDown += generic_PreviewMouseDown(newRadio,?????);
textBlock.Text = listBox.SelectedIndex.ToString();
}
private void text_Selected(object sender, RoutedEventArgs e)
{
TextBox newText = new TextBox();
canvas1.Children.Add(newText);
textBlock.Text = (String)listBox.SelectedIndex.ToString();
}
private void combo_Selected(object sender, RoutedEventArgs e)
{
Console.Write("Combo");
textBlock.Text = (String)listBox.SelectedIndex.ToString();
}
}
Thanks!
If all you want to do is handle the mouse down on the new RadioButton, change this line:
newRadio.PreviewMouseDown += generic_PreviewMouseDown(newRadio,?????);
To this:
newRadio.PreviewMouseDown += generic_PreviewMouseDown;
Edit
And then you need to change the generic_PreviewMouseDown to the following:
private void generic_PreviewMouseDown(object sender, MouseEventArgs e)
{
UIElement elem = sender as UIElement;
Point x = e.GetPosition(canvas1);
if (e.LeftButton == MouseButtonState.Pressed)
{
Canvas.SetLeft(elem, Canvas.GetLeft(elem) + (x.X - p.X));
Canvas.SetTop(elem, Canvas.GetTop(elem) + (x.Y - p.Y));
}
p = x;
}

UserControl PreviewMouseLeftButtonUp problem

I have a UserControl in WPF. I also have a Borderless window. To move it- I use DragMove.
But- to get a click event in the user control- I use the PreviewMouseLeftButtonUp event and capture the mouse on UserControl_MouseEnter.
The problem is- that if I click the control, then move the window- the event can be triggered also when clicking near the control, not on it.
Here is my code:
UserControl1.xaml:
<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" MouseEnter="UserControl_MouseEnter" MouseLeave="UserControl_MouseLeave">
<Grid>
</Grid>
</UserControl>
UserControl1.xaml.cs:
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void UserControl_MouseEnter(object sender, MouseEventArgs e)
{
CaptureMouse();
}
private void UserControl_MouseLeave(object sender, MouseEventArgs e)
{
ReleaseMouseCapture();
}
}
MainWindow.xaml:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525" xmlns:my="clr-namespace:WpfApplication1" WindowStyle="None" MouseLeftButtonDown="Window_MouseLeftButtonDown">
<Grid>
<my:UserControl1 Margin="39,29,380,199" Background="Red" PreviewMouseLeftButtonUp="UserControl1_PreviewMouseLeftButtonUp">
</my:UserControl1>
</Grid>
</Window>
MainWindow.xaml.cs:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
DragMove();
}
private void UserControl1_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("Hello World");
}
}
If you run this app- you'll see that if you click on the control, then drag the window, then click near the control (the side may vary)- it will trigger the PreviewMouseLeftButtonUp event even though you didn't click on the control itself.
Any ideas how to solve this?
Thanks!
I asked around, and found that to solve the problem, I need to change the User control's events:
Instead of MouseLeave- I use MouseMove.
private void UserControl_MouseEnter(object sender, MouseEventArgs e)
{
if (this.IsEnabled)
CaptureMouse();
}
private void UserControl_MouseMove(object sender, MouseEventArgs e)
{
Point mouseposition = e.GetPosition(this);
if (mouseposition.X < 0 || mouseposition.Y < 0 || mouseposition.X > this.ActualWidth || mouseposition.Y > this.ActualHeight)
ReleaseMouseCapture();
}

WPF Not sending MouseMove events after CaptureMouse();

I'm trying to have a WPF canvas with rounded rectangles on that I can drag round using the mouse. However once I try and capture the mouse on the canvas I don't get the move events any more.
This is a "mycanvas" user control and the rectangles are "foo" user controls. The XAML for these (minus the preamble) are:
mycanvas.xaml:
<Canvas MouseDown="CanvasMouseDown" MouseMove="CanvasMouseMove" MouseUp="CanvasMouseUp" Background="White">
<my:Foo HorizontalAlignment="Left" Canvas.Left="97" Canvas.Top="30" x:Name="m_foo" VerticalAlignment="Top" Height="87" Width="128" />
</Canvas>
foo.xaml:
<Border BorderThickness="2" BorderBrush="Black" CornerRadius="15" Background="Plum">
<Grid>
<Label Content="Foo" Height="28" HorizontalAlignment="Left" Margin="6,6,0,0" Name="label1" VerticalAlignment="Top" />
</Grid>
</Border>
And then the handlers are:
mycanvas.xaml.cs:
private void CanvasMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.Source is Foo)
{
m_moving = e.Source as Foo;
CaptureMouse();
e.Handled = true;
}
}
private void CanvasMouseMove(object sender, MouseEventArgs e)
{
if (m_moving != null)
{
Canvas.SetLeft(m_moving, e.GetPosition(this).X);
Canvas.SetTop(m_moving, e.GetPosition(this).Y);
}
}
private void CanvasMouseUp(object sender, MouseButtonEventArgs e)
{
ReleaseMouseCapture();
m_moving = null;
}
The MouseDown fires and so the CaptureMouse gets called (and works because I can no longer close the app or click anything else in it!) but the MouseMove never gets called anymore - so where do the MouseMove events get sent now???
If I alt-tab to another application and then go back now suddendly the MouseMove is called and the Foo moves with the mouse.
Try either:
Mouse.Capture(this, CaptureMode.SubTree);
or
m_moving.CaptureMouse();
...
if (m_moving != null)
{
m_moving.ReleaseMouseCapture();
m_moving = null;
}
The mouse events were being raised by the Foo, not by the Canvas, so when you capture the mouse with the Canvas you prevent them from being raised.
You can directly use the MouseMove event on the Window:
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
this.MouseMove += MouseEventHandler;
}
private void MouseEventHandler(Object sender, MouseEventArgs e)
{
System.Windows.Point position = e.GetPosition(this);
Canvas.SetLeft(ElipseElement, position.X-5);
Canvas.SetTop(ElipseElement, position.Y-5);
}
}

Resources