2021年2月5日星期五

How to bind properties both ways WPF

I am a reeeally noob beginner WPF developer, and getting the hang of c#. I am creating an app, where I need a knob Button and a TextBox Display, where the knob adjusts the text from the display, and the display, if text is changed, updates the knob position.

Inage example of my application

I've managed to create the Knob Button, which spins when clicked and dragged, and also managed to bind it's value to the TextBox, it displays the value perfectly, but I can't make the TextBox Text update the Knob's position, which is defined by Angle variable (from the RotateTransform thing), the code is as follows:

<UserControl x:Class="quaselaeuespero.VolumeControl"               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:quaselaeuespero"               mc:Ignorable="d"                d:DesignHeight="154" d:DesignWidth="148">      <Grid>          <Image Name="aPorradoknob" Source="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>      </Grid>  </UserControl>  
using System;  using System.Collections.Generic;  using System.Linq;  using System.Text;  using System.Threading.Tasks;  using System.Windows;  using System.Windows.Controls;  using System.Windows.Data;  using System.Windows.Documents;  using System.Windows.Input;  using System.Windows.Media;  using System.Windows.Media.Imaging;  using System.Windows.Navigation;  using System.Windows.Shapes;    namespace quaselaeuespero  {      /// <summary>      /// Interaction logic for VolumeControl.xaml      /// </summary>      public partial class VolumeControl : UserControl      {          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.Angle = 120;              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;                  }                    if(this.Angle >= -90 && this.Angle <= -45)                  {                      this.Angle = 270;                  }                    if (this.Angle >= -45 && this.Angle <= 0)                  {                      this.Angle = 1;                  }                  this.Angle = Math.Round(this.Angle, 1);              }          }      }  }    

The Knob is <VolumeControl/> and Display is <DisplayBPM/>, in the main Window I tried to bind them both:

<Window x:Class="quaselaeuespero.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:quaselaeuespero"          mc:Ignorable="d"          Title="MainWindow" Height="540" Width="960">      <Grid>          <Grid.Background>              <ImageBrush ImageSource="Background.png"/>          </Grid.Background>          <local:VolumeControl x:Name="Knobão" Margin="123,240,675,111" RenderTransformOrigin="0.5,0.5" Angle="{Binding ElementName=BPMDisplay, Path=BPM, UpdateSourceTrigger=Explicit}"/>          <local:DisplayBPM x:Name="BPMDisplay" BPM="{Binding ElementName=Knobão, Path=Angle, UpdateSourceTrigger=Explicit}" Margin="68,153,656,274" VerticalAlignment="Center" HorizontalAlignment="Center"/>      </Grid>      </Window>    

The following is the code for DisplayBPM:

<UserControl x:Class="quaselaeuespero.DisplayBPM"               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:quaselaeuespero"               mc:Ignorable="d"                d:DesignHeight="79               " d:DesignWidth="229"               Name="Display">      <Grid Margin="0">          <TextBox x:Name="BPMTexto" Text="{Binding ElementName=Display, Path=BPM}" HorizontalAlignment="Right" Margin="0,0,4,0" Width="222" BorderBrush="{x:Null}" SelectionBrush="{x:Null}" Foreground="#FFCF1D1D" FontSize="80" HorizontalContentAlignment="Center" VerticalContentAlignment="Center" FontFamily="DS-Digital" RenderTransformOrigin="0.5,0.5" CaretBrush="#FFCF1D1D">              <TextBox.Background>                  <ImageBrush ImageSource="Display BPM.png" Stretch="Uniform"/>              </TextBox.Background>          </TextBox>      </Grid>  </UserControl>    

and the DisplayBPM.xaml.cs:

using System;  using System.Collections.Generic;  using System.Linq;  using System.Text;  using System.Threading.Tasks;  using System.Windows;  using System.Windows.Controls;  using System.Windows.Data;  using System.Windows.Documents;  using System.Windows.Input;  using System.Windows.Media;  using System.Windows.Media.Imaging;  using System.Windows.Navigation;  using System.Windows.Shapes;    namespace quaselaeuespero  {      /// <summary>      /// Interaction logic for DisplayBPM.xaml      /// </summary>      public partial class DisplayBPM : UserControl      {          private void BPMTexto_TextChanged(object sender, EventArgs e)          {              BPM = Convert.ToDouble(BPMTexto.Text);           }          public static readonly DependencyProperty BPMProperty =          DependencyProperty.Register("BPM", typeof(double), typeof(DisplayBPM), new UIPropertyMetadata(0.0));          public double BPM          {              get { return (double)GetValue(BPMProperty); }              set { SetValue(BPMProperty, value); }          }          public DisplayBPM()          {              InitializeComponent();              BPM = 1;          }                  }      }    

The problem is that BPM (variable from DisplayBPM, from which TextBox gets its input) doesn't seem to be changed, and if it is changed, it is not changing Angle (variable from RotateTransform that determines the Knob position). Can anyone help me? I know there are probably tons of basic problems, it would really help me if you could explain them to me. Thank you so much!

https://stackoverflow.com/questions/66072286/how-to-bind-properties-both-ways-wpf February 06, 2021 at 08:12AM

没有评论:

发表评论