-1

I am new at WPF and C# but I am picking up quite swiftly thanks to this community. I have tried to implement an Angular Gauge from live charts into my project. It works great with only one binded value and the rest of the values fixed like in this example: (https://lvcharts.net/App/examples/v1/wpf/Angular%20Gauge).

Can someone please help me adapt my code in order to make it dynamic? Instead of having fixed values in FromValue: ToValue: I would like to bind them to values from my database or calculate them based on my target. All suggestions are more than welcome.

Here's what I have so far and works:

XAML:

<lvc:AngularGauge  Value="{Binding Value}" FromValue="0" Grid.Column="1" ToValue="250" 
      LabelsStep="50" TicksStep="25" Wedge="300"
      TicksForeground="White" Foreground="WhiteSmoke" 
      FontWeight="Bold" FontSize="16"
      SectionsInnerRadius=".6" Width="310">
    <lvc:AngularGauge.Sections>
        <lvc:AngularSection FromValue="0" ToValue="62.5" Fill="#dd5143"/>
        <lvc:AngularSection FromValue="62.5" ToValue="125" Fill="#e68523"/>
        <lvc:AngularSection FromValue="125" ToValue="187.5" Fill="#edb220"/>
        <lvc:AngularSection FromValue="175" ToValue="250" Fill="#7cb82f"/>
    </lvc:AngularGauge.Sections>
</lvc:AngularGauge>

C#:

namespace Car_App

    public partial class MainWindow : MetroWindow
    {
        private double _value;

        public MainWindow()
        {
            InitializeComponent();

            string connectionString = "datasource=xx.xx.xxx.xxx;port=xxxx;username=xxxx;password=xxx";
            string sMonth = DateTime.Now.ToString("MM");
            string sYear = DateTime.Now.ToString("yyyy");

            MySqlConnection connection = new MySqlConnection(connectionString);

            MySqlCommand cmd = new MySqlCommand("Select * from Table.MyTable where MONTH(Date) = @sMonth AND YEAR(Date) = @sYear", connection);
            MySqlCommand sCarCT = new MySqlCommand("Select TotalCarCount from Table.CarTotals where sMonth = @sMonth", connection);
            MySqlCommand target = new MySqlCommand("Select Target from Table.Targets where Location = 'xxxxx'", connection);

            try
            {
            connection.Open();
                cmd.Parameters.Add(new MySqlParameter("sMonth", sMonth));
                cmd.Parameters.Add(new MySqlParameter("sYear", sYear));
                sCarCT.Parameters.Add(new MySqlParameter("sMonth", sMonth));

                DataTable dt = new DataTable();
                dt.Load(cmd.ExecuteReader());
                dtGrid.DataContext = dt;

                Value = double.Parse(sCarCT.ExecuteScalar().ToString());
                DataContext = this;

            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            connection.Close();
        }

        public double Value
        {
            get { return _value; }
            set
            {
                _value = value;
            }
        }

    }

What I would like to achieve but doesn't work (I know it doesn't have a chance of working but I am hoping someone could help me rewrite it correctly):

XAML:

<lvc:AngularGauge  Value="{Binding Value}" FromValue="0" Grid.Column="1" ToValue="{Binding ValueT}"
      LabelsStep="50" TicksStep="25" Wedge="300"
      TicksForeground="White" Foreground="WhiteSmoke" 
      FontWeight="Bold" FontSize="16"
      SectionsInnerRadius=".6" Width="310">
    <lvc:AngularGauge.Sections>
        <lvc:AngularSection FromValue="0" ToValue="{Binding Value25}" Fill="#dd5143"/>
        <lvc:AngularSection FromValue="{Binding Value25}" ToValue="{Binding Value50}" Fill="#e68523"/>
        <lvc:AngularSection FromValue="{Binding Value50}" ToValue="{Binding Value75}" Fill="#edb220"/>
        <lvc:AngularSection FromValue="{Binding Value75}" ToValue="{Binding ValueT}" Fill="#7cb82f"/>
    </lvc:AngularGauge.Sections>
</lvc:AngularGauge>

C#:

namespace Car_App

    public partial class MainWindow : MetroWindow
    {
        private double _value;

        public MainWindow()
        {
            InitializeComponent();

            string connectionString = "datasource=xx.xx.xxx.xxx;port=xxxx;username=xxxx;password=xxx";
            string sMonth = DateTime.Now.ToString("MM");
            string sYear = DateTime.Now.ToString("yyyy");

            MySqlConnection connection = new MySqlConnection(connectionString);

            MySqlCommand cmd = new MySqlCommand("Select * from Table.Car where MONTH(Date) = @sMonth AND YEAR(Date) = @sYear", connection);
            MySqlCommand sCarCT = new MySqlCommand("Select TotalCarCount from Table.CarTotals where sMonth = @sMonth", connection);
            MySqlCommand target = new MySqlCommand("Select Target from Table.Targets where Location = 'xxxxx'", connection);

            try
            {
            connection.Open();
                cmd.Parameters.Add(new MySqlParameter("sMonth", sMonth));
                cmd.Parameters.Add(new MySqlParameter("sYear", sYear));
                sCR.Parameters.Add(new MySqlParameter("sMonth", sMonth));


                DataTable dt = new DataTable();
                dt.Load(cmd.ExecuteReader());
                dtGrid.DataContext = dt;


                Value = double.Parse(sCarCT.ExecuteScalar().ToString());

                ValueT = double.Parse(target.ExecuteScalar().ToString());

                Value75 = ValueT - ValueT*25%;

                Value50 = ValueT - ValueT*50%;

                Value25 = ValueT - ValueT*75%;    

                DataContext = this.Value, this.ValuT, this.Value25, this.Value50, this.Value75;


            }

            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
            connection.Close();
        }


        public double Value
        {
            get { return _value; }
            set
            {
                _value = value;
            }
        }

        public double ValueT
        {
            get { return _value; }
            set
            {
                _value = value;

            }
        }

        public double Value75
        {
            get { return _value; }
            set
            {
                _value = value;
            }
        }

        public double Value50
        {
            get { return _value; }
            set
            {
                _value = value;
            }
        }

        public double Value25
        {
            get { return _value; }
            set
            {
                _value = value;
            }
        }

    }
Cosmin
  • 565
  • 1
  • 8
  • 33
  • 1
    Your question is very broad, especially lacking a good [mcve]. But it doesn't appear you have implemented `INotifyPropertyChanged` in your `MainWindow` class. You would be better off creating a separate view model class for those properties, but either way the class the properties belong to needs to implement `INotifyPropertyChanged` if you want the binding to reflect values set after the binding has been initialized. – Peter Duniho Sep 25 '17 at 18:47
  • Hello Peter! I am sorry I couldn't follow the guidelines. The first example if verifiable and works. Then second one serves as a way to translate what I am trying to achieve. I don't know exactly how to write and I was counting on someone like you, who is way more knowledgeable to help me out. Thank you for your prompt suggestion. – Cosmin Sep 25 '17 at 18:57
  • Your problem has nothing to do with the special gauge or LiveCharts. To make a good Stack Overflow question, you need to provide a code example that distills the basic issue into the _minimal_ amount of code required to demonstrate the problem you're having. Or, you know, you could just read any of the many tutorials about WPF and data binding. That would work too. – Peter Duniho Sep 25 '17 at 18:58
  • Well I am sorry if my question is not good enough for you. I already stripped a lot a code out in order to make it minimal. I am demonstrating what works and what doesn't work. Reading tutorials doesn't help me on this particular problem, I already did that. I understand that you're trying to help me write better questions and examples in the future but I would appreciate it if you could give me a hand with this particular example, like other members of this community. I agree with you that it might not be the best example but I didn't know how to lay it out better. Cheers! – Cosmin Sep 25 '17 at 19:11

1 Answers1

2

I'm not familiar with this particular library but looking at the source code shows that the FromValue and ToValue properties are dependency properties so binding them to a value is possible. It looks like it may simply be a matter of you not implementing your value properties as DependencyProperty.

Try implementing your properties similar to this:

public static readonly DependencyProperty Value25Property = DependencyProperty.Register(
    "Value25", 
    typeof(double), 
    typeof(MainWindow));

public double Value25
{
    get { return (double) GetValue(Value25Property); }
    set { SetValue(Value25Property, value); }
}
Jason Boyd
  • 6,839
  • 4
  • 29
  • 47
  • 2
    The source property does not need to be `DependencyProperty` for a binding to work. – Peter Duniho Sep 25 '17 at 18:48
  • 1
    @PeterDuniho The source property does not need to be a `DependencyProperty` for the initial binding to work. In this case the properties all have a default value of 0 and they are being explicitely set. So they will need to be implemented as `DepenceyProperties` or the OP will have to implement `INotifyPropertyChanged`. – Jason Boyd Sep 25 '17 at 18:51
  • Thank you so much for the prompt responses. I am really new at this. Can you please show me how can I implement DependencyProperty. I have no clue where to start. – Cosmin Sep 25 '17 at 18:53
  • 1
    @Jason: The properties being bound _can_ be implemented as dependency properties, but since they aren't properties of the _window_, nor need to be targets of a binding, doing so doesn't make sense, and recommending that they be done that way to someone new to WPF is over-complicating their scenario for no good reason. All they need is a proper view model, just like any good WPF program. – Peter Duniho Sep 25 '17 at 19:00
  • 1
    @PeterDuniho I get your point about the view model and agree it is the 'correct' way when developing a WPF application but explaining MVVM in depth seems beyond the scope of the question. The OP had a specific question regarding binding `AngularSection` properties to properties on a `MainWindow`. – Jason Boyd Sep 25 '17 at 19:08
  • 1
    @Jason: _"explaining MVVM in depth seems beyond the scope of the question"_ -- explaining MVVM in depth is exactly what the question calls for, which is why it's too broad. It really shouldn't have been answered, IMHO. If you are going to answer a question that's too broad, you need to do it right. Don't compound the OP's confusion by teaching him the wrong thing. – Peter Duniho Sep 25 '17 at 19:11
  • Peter, can you please point me in the right direction? I would like to understand MVVM better using this example. What would be the right approach? Can you please show me how to write that proper view model? – Cosmin Sep 25 '17 at 19:17
  • 1
    @EdPlunkett Hi Ed, I do understand that INPC is the standard practice when working with view models. But there is no view model that implements `INotifyPropertyChanged` in the example code posted in the question. There is a `MainWindow` which is a `DependencyObject` hence my recommendation to use a `DependencyProperty`. I think you may have assumed their was a view model due to Peter's comments. – Jason Boyd Sep 25 '17 at 19:29
  • Jason, you are right, I am not using a view model because I am not really familiar with MVVM pattern. I am only using a mainwindow. I Have tried using DependecyProperty like you have shown me but it didn't work, VS just crashes. Do you have other suggestions? What I am doing wrong and what the quickest fix? Thank you! – Cosmin Sep 27 '17 at 00:07