WPF 音量拨号代码教程代码在我的代码中有问题,但在教程代码中没有问题

Posted

技术标签:

【中文标题】WPF 音量拨号代码教程代码在我的代码中有问题,但在教程代码中没有问题【英文标题】:WPF volume dial code tutorial code has issues in my code but none in the tutorial code 【发布时间】:2021-11-08 18:02:40 【问题描述】:

大家好,我需要一些帮助才能使下面的代码正常工作。我正在关注this tutorial,大多数事情都可以正常工作,但代码中有一些事情由于某种原因似乎无法正常工作。所有这些代码看起来都像教程中的代码,所以我不确定发生了什么?

用户控制xaml代码:

<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>

后面的代码:

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;
        
    

目前的问题是:

e.位置 错误:

错误 CS1061 'ManipulationDeltaEventArgs' 不包含 'Position' 的定义并且没有可访问的扩展方法 'Position' 接受类型的第一个参数 可以找到“ManipulationDeltaEventArgs”(您是否缺少使用 指令还是程序集引用?)

设置属性 错误:

错误 CS7036 没有给出对应于 'dial.SetProperty(ref T, T, ?)'的必需形参''

CallerMemberName 错误:

错误 CS1061 'ManipulationDeltaEventArgs' 不包含 'Position' 的定义并且没有可访问的扩展方法 'Position' 接受类型的第一个参数 可以找到“ManipulationDeltaEventArgs”(您是否缺少使用 指令还是程序集引用?)

在 xaml 用户控件上:

错误操作在指定元素上未激活。

不知道为什么我会收到这些错误,因为它与视频教程的代码相同,并且没有像我的那样显示错误..

更新 #1

更新 #2 代码应该产生一个拨号:

更新 #3:让鼠标充当触控设备

在BlakeNUI中添加MouseTouchDevice.cs类:

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;

到我的项目并放置:

public watchingMovie(String movie)

    InitializeComponent();
    MouseTouchDevice.RegisterEvents(this);
    ...

让它像在触摸设备上一样工作。

【问题讨论】:

请see 这个,我知道它不能在那里编译,它只是代码的占位符。我可以通过一些更改进行编译。你知道ManipulationDeltaEventArgs 是正确的;我无法对此进行测试,但我能够改变角度并且白色圆圈确实移动了......测试我的更改并让我知道它们是否有效。 包含链接的教程是用 UWP 而非 WPF 编写的。 @zaggler 我做了这些修改,看起来后面的代码不再有错误。但是,xaml 现在似乎有了它们,因此我无法编译和测试。 user9938 - 哼我不知道。 Surly 这可以轻松适应 WPF 吗? @zaggler 错误操作在指定元素上未激活。 继续,然后将您的项目压缩并发布,然后尝试加载它。也请继续将此添加到您的答案中,这样该评论部分就不会永远持续下去。 【参考方案1】:

尝试在事件处理程序中将e.Position 替换为e.ManipulationOrigin,并在XAML 标记中将GridIsManipulationEnabled 属性设置为true

<Grid  IsManipulationEnabled="True" ...

您还需要实际实现SetProperty&lt;T&gt; 方法。

【讨论】:

对不起,我不是故意要对这个做-1!对不起! 是的,但不确定谁将我的 OP 否决为 -2? @StealthRT 老实说发生了很多事情,我给了它一个赞成票,因为这是一个具有可重现问题的明确问题。【参考方案2】:

目前的问题是:

错误 CS1061“ManipulationDeltaEventArgs”不包含“Position”的定义,并且找不到接受“ManipulationDeltaEventArgs”类型的第一个参数的可访问扩展方法“Position”(您是否缺少 using 指令或程序集引用?)

此错误是因为它不存在,您可以将.Position 替换为ManipulationOrigin,它会获取操作的起始点并返回System.Windows.Point

 this.Angle = GetAngle(e.ManipulationOrigin, this.RenderSize);
 

错误 CS7036 没有给出与 'dial.SetProperty(ref T, T, ?)' 的所需形参 '' 对应的参数

请参见下面的示例实现:

 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;
 

错误操作在指定元素上未激活。

要解决此问题,请在网格本身上设置 IsManipulationEnabled="True",这意味着为 UIElement 启用了操作

所有这些都结束了:

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>

【讨论】:

我想补充一下,正如 zaggle 所说,这不会起作用,因为它只是触摸所以我更新了我的 OP 以反映这种变化,以便使用鼠标作为触摸。

以上是关于WPF 音量拨号代码教程代码在我的代码中有问题,但在教程代码中没有问题的主要内容,如果未能解决你的问题,请参考以下文章

C# WPF 后台代码怎样实现 RenderTransform 效果呢?

WPF中怎么在后台代码里面选中ListView的Items?

SystemSoundID 有时会随设备音量而变化

在我的项目中构建和重用 android 开源 Dialer 源代码

如何在 WPF 中更改数据网格标题样式或元素样式前景

如何将国家拨号代码放在 intlTelInput 中的括号中