Digital Gauge CharacterHeight and CharacterPadding in %

Gauge for WPF Forum

Posted 13 years ago by 7Alpha7
Avatar
While resizing a digital gauge the characters don't fit the new size well. It would be appreciated to apply to them % values rather than absolute one, like it is done with major circular gauges properties for example.

I saw that there is the double.NaN trick. First, id does not allow to choose oneself the ratio of the character height from the total height. And if I set the CharacterHeight to double.NaN my application crashes when I want to resize it with the error message : "negative height" or something like that.

[Modified at 03/10/2011 01:55 AM]

[Modified at 03/10/2011 01:57 AM]

Comments (8)

Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hi,

We've marked down a TODO item to add support for percentage based heights in the future. Thanks for the suggestion.

The CharacterHeight property defaults to double.NaN, but can also be set to a positive value (i.e. >= 0). It does not support negative numbers. Also, if you are try to set CharacterHeight="NaN", then that will not work. You'd need to do CharacterHeight="Auto".

Regardless, you shouldn't be able to set CharacterHeight to a negative value, since we include a ValidationCallback that prevents those values. Your configuration probably triggers something that results in a negative value when rendering/measuring. If you can send over a small sample project that reproduces the issue to our support address then we can take a closer look.


Actipro Software Support

Posted 13 years ago by 7Alpha7
Avatar
For the negative value issue, the things are simple : I have a digital view hosted in a ElementHost; the eEementHost is in a TableLayoutPanel cell. When I resize the main form displaying the digital view, I have this Exception when the digital gauge becomes not visible anymore due to resizing :

SystemArgumentException in WindowsBase; Width must not have a negative value

   à System.Windows.Size.set_Width(Double value)
   à <b>ActiproSoftware.Windows.Controls.Gauge.DigitalGauge.MeasureOverride(Size availableSize)</b>   à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   à System.Windows.UIElement.Measure(Size availableSize)
   à MS.Internal.Helper.MeasureElementWithSingleChild(UIElement element, Size constraint)
   à System.Windows.Controls.ContentPresenter.MeasureOverride(Size constraint)
   à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   à System.Windows.UIElement.Measure(Size availableSize)
   à System.Windows.Controls.Border.MeasureOverride(Size constraint)
   à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   à System.Windows.UIElement.Measure(Size availableSize)
   à System.Windows.Controls.Control.MeasureOverride(Size constraint)
   à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   à System.Windows.UIElement.Measure(Size availableSize)
   à System.Windows.Controls.DockPanel.MeasureOverride(Size constraint)
   à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   à System.Windows.UIElement.Measure(Size availableSize)
   à System.Windows.Controls.Decorator.MeasureOverride(Size constraint)
   à System.Windows.Documents.AdornerDecorator.MeasureOverride(Size constraint)
   à System.Windows.FrameworkElement.MeasureCore(Size availableSize)
   à System.Windows.UIElement.Measure(Size availableSize)
   à System.Windows.Interop.HwndSource.Process_WM_SIZE(UIElement rootUIElement, IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam)
   à System.Windows.Interop.HwndSource.LayoutFilterMessage(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   à MS.Win32.HwndWrapper.WndProc(IntPtr hwnd, Int32 msg, IntPtr wParam, IntPtr lParam, Boolean& handled)
   à MS.Win32.HwndSubclass.DispatcherCallbackOperation(Object o)
   à System.Windows.Threading.ExceptionWrapper.InternalRealCall(Delegate callback, Object args, Boolean isSingleParameter)
   à System.Windows.Threading.ExceptionWrapper.TryCatchWhen(Object source, Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler)
   à System.Windows.Threading.Dispatcher.WrappedInvoke(Delegate callback, Object args, Boolean isSingleParameter, Delegate catchHandler).........
[Modified at 03/10/2011 10:14 PM]

[Modified at 03/11/2011 07:56 AM]
Posted 13 years ago by 7Alpha7
Avatar
Here is the code necessary to reproduce the bug.

- Create a WinForm project
- Copy/paste C# code in Program.cs file
- Create a .xoml WPF control
- Copy code the XAML code in it
- Add necessary references
- Run the code

You will see that;

ONE : if you resize the form, making it bigger, the character auto resizing feature is not well suited as the character height is never the proper one regarding of the digital gauge height;

TWO : if you resize the form very small you'll get a Negative Height argument exception.

A good auto resize feature is really important for me because my application will be deployed on different targets with many different screen resolutions. I need to rely on a good resizing treatment, as good as the one one can find in circular gauges for examples, by the use of %.

Thank you.

using System;
using System.Collections.Generic;
using System.Linq;
using System.Windows.Forms;

namespace test {
    static class Program {
        /// <summary>
        /// Point d'entrée principal de l'application.
        /// </summary>
        [STAThread]
        static void Main() {
            Application.EnableVisualStyles();
            Application.SetCompatibleTextRenderingDefault(false);
            Application.Run(new Form1());
        }
    }

    public partial class DigitalGauge : System.Windows.Controls.UserControl {
        public DigitalGauge() {
            InitializeComponent();
        }
    }

    public class Form1 : Form {

        public Form1() {
            InitializeComponent();
            elementHost1.Child = new DigitalGauge();
        }

        /// <summary>
        /// Variable nécessaire au concepteur.
        /// </summary>
        private System.ComponentModel.IContainer components = null;

        /// <summary>
        /// Nettoyage des ressources utilisées.
        /// </summary>
        /// <param name="disposing">true si les ressources managées doivent être supprimées ; sinon, false.</param>
        protected override void Dispose(bool disposing) {
            if (disposing && (components != null)) {
                components.Dispose();
            }
            base.Dispose(disposing);
        }

        #region Code généré par le Concepteur Windows Form

        /// <summary>
        /// Méthode requise pour la prise en charge du concepteur - ne modifiez pas
        /// le contenu de cette méthode avec l'éditeur de code.
        /// </summary>
        private void InitializeComponent() {
            this.elementHost1 = new System.Windows.Forms.Integration.ElementHost();
            this.tableLayoutPanel1 = new System.Windows.Forms.TableLayoutPanel();
            this.tableLayoutPanel1.SuspendLayout();
            this.SuspendLayout();
            // 
            // elementHost1
            // 
            this.elementHost1.Dock = System.Windows.Forms.DockStyle.Fill;
            this.elementHost1.Location = new System.Drawing.Point(3, 3);
            this.elementHost1.Name = "elementHost1";
            this.elementHost1.Size = new System.Drawing.Size(95, 46);
            this.elementHost1.TabIndex = 0;
            this.elementHost1.Text = "elementHost1";
            this.elementHost1.Child = null;
            // 
            // tableLayoutPanel1
            // 
            this.tableLayoutPanel1.Anchor = ((System.Windows.Forms.AnchorStyles)((((System.Windows.Forms.AnchorStyles.Top | System.Windows.Forms.AnchorStyles.Bottom)
                        | System.Windows.Forms.AnchorStyles.Left)
                        | System.Windows.Forms.AnchorStyles.Right)));
            this.tableLayoutPanel1.ColumnCount = 2;
            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
            this.tableLayoutPanel1.ColumnStyles.Add(new System.Windows.Forms.ColumnStyle(System.Windows.Forms.SizeType.Percent, 50F));
            this.tableLayoutPanel1.Controls.Add(this.elementHost1, 0, 0);
            this.tableLayoutPanel1.Location = new System.Drawing.Point(0, 0);
            this.tableLayoutPanel1.Name = "tableLayoutPanel1";
            this.tableLayoutPanel1.RowCount = 2;
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
            this.tableLayoutPanel1.RowStyles.Add(new System.Windows.Forms.RowStyle(System.Windows.Forms.SizeType.Percent, 50F));
            this.tableLayoutPanel1.Size = new System.Drawing.Size(203, 105);
            this.tableLayoutPanel1.TabIndex = 1;
            // 
            // Form1
            // 
            this.AutoScaleDimensions = new System.Drawing.SizeF(11F, 24F);
            this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
            this.ClientSize = new System.Drawing.Size(322, 207);
            this.Controls.Add(this.tableLayoutPanel1);
            this.Font = new System.Drawing.Font("Microsoft Sans Serif", 14F, System.Drawing.FontStyle.Regular, System.Drawing.GraphicsUnit.Point, ((byte)(0)));
            this.Margin = new System.Windows.Forms.Padding(5, 6, 5, 6);
            this.Name = "Form1";
            this.Text = "Form1";
            this.tableLayoutPanel1.ResumeLayout(false);
            this.ResumeLayout(false);

        }

        #endregion

        private System.Windows.Forms.Integration.ElementHost elementHost1;
        private System.Windows.Forms.TableLayoutPanel tableLayoutPanel1;

    }
}


<UserControl x:Class="test.DigitalGauge"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:shared="http://schemas.actiprosoftware.com/winfx/xaml/shared"
    Height="170" Width="348" xmlns:gauge="http://schemas.actiprosoftware.com/winfx/xaml/gauge" Background="Transparent">
    <gauge:DigitalGauge x:Name="gauge" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Value="0"
                            CharacterCount="10" Foreground="Cyan" Background="Black" CharacterPadding="10,0" BackgroundType="RoundedRectangleLightGradient"
                        RimType="RoundedRectangleLightGradient" CharacterType="DotMatrix5By7Rectangle"  GlassType="RoundedRectangle">        

    </gauge:DigitalGauge>
</UserControl>
[Modified at 03/11/2011 07:57 AM]

[Modified at 03/11/2011 07:59 AM]

[Modified at 03/11/2011 08:00 AM]
Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Hello,

For some reason I was still unable to reproduce the crash using the steps you provided. In general, it is easier if you just send an entire sample project that reproduces the issue, which we can compile and run. Often times when pasting code in the forums, the piece that is causing the issue is not included because it didn't seem important/relavent. In this case, it seems like it should have triggered a crash, but is wasn't.

Regardless, based on your stack trace we were able to determine the issue and correct it. This will be included in the next maintenance release.

The issue with the height has to do with your CharacterPadding and the number of characters you are trying to display. When you start to size the DigitalGauge smaller, the 20 pixel padding you define takes up more space relative to the size the characters. They are rendering in the space given.

As for a workaround, your best bet would be to design your DigitalGauge at a fixed size and use a Viewbox to perform the dynamic sizing.


Actipro Software Support

Posted 13 years ago by 7Alpha7
Avatar
"As for a workaround, your best bet would be to design your DigitalGauge at a fixed size and use a Viewbox to perform the dynamic sizing."

I even don't know what a Viewbox is. I don't want to spend days mastering WPF and my best bet according to me is to put a well designed WPF control in a Element Host and put the element host in a windows form solution which I master pretty well, without caring at all about what WPF is doing in the background.

If I can do this for a CircularGauge, I expect to be able to do this with a DigitalGauge. I think this is a reasonable expectation.
Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
As mentioned above, we think we've fixed the issue for the next maintenance release. So once that is out, no workaround would be necessary. We just did a release several days ago so the next might not be until April.


Actipro Software Support

Posted 13 years ago by Actipro Software Support - Cleveland, OH, USA
Avatar
Sorry, the last post should have said we fix the issue with the exception. Adding percentage based sizing is a larger change, which we intend to add in the future.

Unfortunately, the only workaround is to use a Viewbox, which is well documented (see hereand here). You'd need to do something like:
<Viewbox Stretch="UniformFill">
    <gauge:DigitalGauge ... />
</Viewbox>


Actipro Software Support

Posted 13 years ago by 7Alpha7
Avatar
I did it already and it worked well than you.
The latest build of this product (v24.1.1) was released 1 month ago, which was after the last post in this thread.

Add Comment

Please log in to a validated account to post comments.