Hey all I need some help with getting the code below working. I was following this tutorial and most things work but there are a few things in the code that seem not to work for some reason. All this code looks like the code in the tutorial so I'm unsure of what's going on?
User control xaml code:
<UserControl x:Class="carProg.dial"
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"
xmlns:local="clr-namespace:carProgForKids"
mc:Ignorable="d" Height="450" Width="450">
<Grid Manipulation.ManipulationMode="All" ManipulationDelta="Grid_ManipulationDelta">
<Ellipse Stroke="Black" Margin="30" Fill="#FFFFE15D"/>
<Grid>
<Grid.RenderTransform>
<RotateTransform CenterX="225" CenterY="225" Angle="{Binding Angle}" />
</Grid.RenderTransform>
<Ellipse Fill="#FFFFFDF3"
Height="100" Stroke="Black" Margin="0"
VerticalAlignment="Top" Width="100"/>
</Grid>
</Grid>
</UserControl>
Code behind:
using System;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace carProg
{
public partial class dial : UserControl, INotifyPropertyChanged
{
public dial()
{
InitializeComponent();
this.DataContext = this;
}
private void Grid_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
this.Angle = GetAngle(e.Position, this.RenderSize);
this.Amount = (int)(this.Angle / 360 * 100);
}
int m_Amount = default(int);
public int Amount {
get { return m_Amount; }
set { SetProperty(ref m_Amount, value);
} }
double m_Angle = default(double);
public double Angle {
get { return m_Angle; }
set { SetProperty(ref m_Angle, value);
} }
public event PropertyChangedEventHandler PropertyChanged;
void SetProperty<T>(ref T storage, T value, [System.Runtime.CompilerServices.CallerMemberName]);
public enum Quadrants : int { nw = 2, ne = 1, sw = 4, se = 3 }
private double GetAngle(Point touchPoint, Size circleSize)
{
var _X = touchPoint.X - (circleSize.Width / 2d);
var _Y = circleSize.Height - touchPoint.Y - (circleSize.Height / 2d);
var _Hypot = Math.Sqrt(_X * _X + _Y * _Y);
var _Value = Math.Asin(_Y / _Hypot) * 180 / Math.PI;
var _Quadrant = (_X >= 0) ?
(_Y >= 0) ? Quadrants.ne : Quadrants.se :
(_Y >= 0) ? Quadrants.nw : Quadrants.sw;
switch (_Quadrant)
{
case Quadrants.ne: _Value = 090 - _Value; break;
case Quadrants.nw: _Value = 270 + _Value; break;
case Quadrants.se: _Value = 090 - _Value; break;
case Quadrants.sw: _Value = 270 + _Value; break;
}
return _Value;
}
}
}
Currently the issues are:
e.Position Error:
Error CS1061 'ManipulationDeltaEventArgs' does not contain a definition for 'Position' and no accessible extension method 'Position' accepting a first argument of type 'ManipulationDeltaEventArgs' could be found (are you missing a using directive or an assembly reference?)
SetProperty Error:
Error CS7036 There is no argument given that corresponds to the required formal parameter '' of 'dial.SetProperty(ref T, T, ?)'
CallerMemberName Error:
Error CS1061 'ManipulationDeltaEventArgs' does not contain a definition for 'Position' and no accessible extension method 'Position' accepting a first argument of type 'ManipulationDeltaEventArgs' could be found (are you missing a using directive or an assembly reference?)
And on the xaml user control:
<Grid Manipulation.ManipulationMode="All" Error:
Error Manipulation is not active on the specified element.
Not sure why I am getting these errors since it's the same code the video tutorial is going off of and it has no errors showing like mine does..
UPDATE #2 The code should produce a dial:
UPDATE #3: Let mouse act as touch device
Adding the MouseTouchDevice.cs class in BlakeNUI:
public class MouseTouchDevice : TouchDevice, ITouchDevice
{
//Class Members
private static MouseTouchDevice device;
public Point Position { get; set; }
//Public Static Methods
public static void RegisterEvents(FrameworkElement root)
{
root.PreviewMouseDown += MouseDown;
root.PreviewMouseMove += MouseMove;
root.PreviewMouseUp += MouseUp;
root.LostMouseCapture += LostMouseCapture;
root.MouseLeave += MouseLeave;
}
//Private Static Methods
private static void MouseDown(object sender, MouseButtonEventArgs e)
{
if (device != null &&
device.IsActive)
{
device.ReportUp();
device.Deactivate();
device = null;
}
device = new MouseTouchDevice(e.MouseDevice.GetHashCode());
device.SetActiveSource(e.MouseDevice.ActiveSource);
device.Position = e.GetPosition(null);
device.Activate();
device.ReportDown();
}
private static void MouseMove(object sender, MouseEventArgs e)
{
if (device != null &&
device.IsActive)
{
device.Position = e.GetPosition(null);
device.ReportMove();
}
}
private static void MouseUp(object sender, MouseButtonEventArgs e)
{
LostMouseCapture(sender, e);
}
static void LostMouseCapture(object sender, MouseEventArgs e)
{
if (device != null &&
device.IsActive)
{
device.Position = e.GetPosition(null);
device.ReportUp();
device.Deactivate();
device = null;
}
}
static void MouseLeave(object sender, MouseEventArgs e)
{
LostMouseCapture(sender, e);
}
//Constructors
public MouseTouchDevice(int deviceId) :
base(deviceId)
{
Position = new Point();
}
//Overridden methods
public override TouchPointCollection GetIntermediateTouchPoints(IInputElement relativeTo)
{
return new TouchPointCollection();
}
public override TouchPoint GetTouchPoint(IInputElement relativeTo)
{
Point point = Position;
}
to my project and placing this:
public watchingMovie(String movie)
{
InitializeComponent();
MouseTouchDevice.RegisterEvents(this);
...
}
Allows it to function as if you were working with it on a touch device.
Currently the issues are:
Error CS1061 'ManipulationDeltaEventArgs' does not contain a definition for 'Position' and no accessible extension method 'Position' accepting a first argument of type 'ManipulationDeltaEventArgs' could be found (are you missing a using directive or an assembly reference?)
This error is because it doesn't exist, you can replace .Position
with ManipulationOrigin which gets the point from which the manipulation originated and returns a System.Windows.Point
:
this.Angle = GetAngle(e.ManipulationOrigin, this.RenderSize);
Error CS7036 There is no argument given that corresponds to the required formal parameter '' of 'dial.SetProperty(ref T, T, ?)'
Please see example implementation below:
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
storage = value;
OnPropertyChanged(propName);
return true;
}
Error Manipulation is not active on the specified element.
To fix this issue set IsManipulationEnabled="True" on the grid iteself which means manipulation is enabled for the UIElement
All of this wrapped up:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
namespace carProg
{
/// <summary>
/// Interaction logic for dial.xaml
/// </summary>
public partial class dial : UserControl, INotifyPropertyChanged
{
public dial()
{
InitializeComponent();
this.DataContext = this;
}
private void Grid_ManipulationDelta(object sender, ManipulationDeltaEventArgs e)
{
this.Angle = GetAngle(e.ManipulationOrigin, this.RenderSize);
this.Amount = (int)(this.Angle / 360 * 100);
}
int m_Amount = default(int);
public int Amount
{
get { return m_Amount; }
set
{
SetProperty(ref m_Amount, value);
}
}
double m_Angle = default(double);
public double Angle
{
get { return m_Angle; }
set
{
SetProperty(ref m_Angle, value);
}
}
// Please note the changes with OnPropertyChanged and SetProperty
public event PropertyChangedEventHandler PropertyChanged;
protected void OnPropertyChanged(string propertyName) => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
protected bool SetProperty<T>(ref T storage, T value, [CallerMemberName] string propName = "")
{
if (EqualityComparer<T>.Default.Equals(storage, value)) return false;
storage = value;
OnPropertyChanged(propName);
return true;
}
public enum Quadrants : int { nw = 2, ne = 1, sw = 4, se = 3 }
private double GetAngle(Point touchPoint, Size circleSize)
{
var _X = touchPoint.X - (circleSize.Width / 2d);
var _Y = circleSize.Height - touchPoint.Y - (circleSize.Height / 2d);
var _Hypot = Math.Sqrt(_X * _X + _Y * _Y);
var _Value = Math.Asin(_Y / _Hypot) * 180 / Math.PI;
var _Quadrant = (_X >= 0) ?
(_Y >= 0) ? Quadrants.ne : Quadrants.se :
(_Y >= 0) ? Quadrants.nw : Quadrants.sw;
switch (_Quadrant)
{
case Quadrants.ne: _Value = 090 - _Value; break;
case Quadrants.nw: _Value = 270 + _Value; break;
case Quadrants.se: _Value = 090 - _Value; break;
case Quadrants.sw: _Value = 270 + _Value; break;
}
return _Value;
}
}
}
// Please note: IsManipulationEnabled on the grid
<Grid IsManipulationEnabled="True" ManipulationDelta="Grid_ManipulationDelta">
<Ellipse Margin="30"
Fill="#FFFFE15D"
Stroke="Black"
/>
<Grid>
<Grid.RenderTransform>
<RotateTransform Angle="{Binding Angle}" CenterX="225" CenterY="225" />
</Grid.RenderTransform>
<Ellipse Width="100"
Height="100"
Margin="0"
VerticalAlignment="Top"
Fill="#FFFFFDF3"
Stroke="Black"
/>
</Grid>
</Grid>