no he visto ningún tipo de control como éste en todo (a pesar de que ha pasado un tiempo desde que miraba todos los controles que los proveedores de control de WPF estaban ofreciendo), pero es relativamente sencillo para crear una.
Todo lo que tendría que hacer es crear un control personalizado que contiene una imagen (o dibujo XAML) que se puede girar para seguir al ratón. A continuación, enlazar un RotateTransform a un DependencyProperty 'Angle' en el control personalizado de manera que cuando se actualiza 'ángulo', la imagen/dibujo gira para que coincida con:
<UserControl x:Class="VolumeControlLibrary.VolumeControl"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:VolumeControlLibrary"
Height="60" Width="60">
<Image Source="/VolumeControl;component/knob.png" RenderTransformOrigin="0.5,0.5" >
<Image.RenderTransform>
<RotateTransform Angle="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type local:VolumeControl}}, Path=Angle}"/>
</Image.RenderTransform>
</Image>
</UserControl>
Configuración RenderTransformOrigin a "0,5, 0,5" garantiza que la el control gira alrededor de su centro, en lugar de girar alrededor de la esquina superior izquierda; también tendremos que compensar esto en el cálculo del ángulo.
En el código detrás de archivo para su control, agregar controladores para el ratón y el DependencyProperty Ángulo:
public partial class VolumeControl : UserControl
{
// Using a DependencyProperty backing store for Angle.
public static readonly DependencyProperty AngleProperty =
DependencyProperty.Register("Angle", typeof(double), typeof(VolumeControl), new UIPropertyMetadata(0.0));
public double Angle
{
get { return (double)GetValue(AngleProperty); }
set { SetValue(AngleProperty, value); }
}
public VolumeControl()
{
InitializeComponent();
this.MouseLeftButtonDown += new MouseButtonEventHandler(OnMouseLeftButtonDown);
this.MouseUp += new MouseButtonEventHandler(OnMouseUp);
this.MouseMove += new MouseEventHandler(OnMouseMove);
}
private void OnMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Mouse.Capture(this);
}
private void OnMouseUp(object sender, MouseButtonEventArgs e)
{
Mouse.Capture(null);
}
private void OnMouseMove(object sender, MouseEventArgs e)
{
if (Mouse.Captured == this)
{
// Get the current mouse position relative to the volume control
Point currentLocation = Mouse.GetPosition(this);
// We want to rotate around the center of the knob, not the top corner
Point knobCenter = new Point(this.ActualHeight/2, this.ActualWidth/2);
// Calculate an angle
double radians = Math.Atan((currentLocation.Y - knobCenter.Y)/
(currentLocation.X - knobCenter.X));
this.Angle = radians * 180/Math.PI;
// Apply a 180 degree shift when X is negative so that we can rotate
// all of the way around
if (currentLocation.X - knobCenter.X < 0)
{
this.Angle += 180;
}
}
}
}
captura el ratón asegura que su control continuará recibiendo actualizaciones del ratón, incluso cuando los ratones de usuario fuera de el control (hasta que suelten el clic), y al obtener la posición del mouse relativa al elemento actual (el control), su cálculo siempre debe ser el mismo independientemente de dónde se represente realmente el control en la pantalla.
En este ejemplo, cuando se mueve el ratón se calcula el ángulo entre ella y el centro del control, y a continuación, ajuste este ángulo a la DependencyProperty ángulo que hemos creado. Como la imagen que mostramos está vinculada a esta propiedad de ángulo, WPF aplica automáticamente el nuevo valor, lo que hace que la perilla gire en combinación con el movimiento del mouse.
Uso del control en su solución es fácil; sólo tiene que añadir:
<local:VolumeControl />
Se podría obligar a la propiedad de ángulo de VolumeControl si desea enlazar el valor de la perilla para algo en su aplicación; ese valor está actualmente en grados, pero podría agregar una propiedad adicional para convertir un ángulo en grados y un valor que tenga sentido para usted (por ejemplo, un valor de 0 a 10).
No puedo entender dónde poner cada bit de código. Estoy teniendo problemas especialmente para hacer funcionar la parte DependencyProperty. –
Bien, puse todo el código en un control de usuario y actualicé la publicación; debería poder copiar y pegar el código en su solución. –
Buena solución: si quieres ir más simple, muchos controles simplemente toman el dY del movimiento del mouse y lo traducen al valor del dial. –