Make the ProgressRing in MahApps.Metro Smaller

2019-04-07 20:06发布

问题:

It looks like the MahApps.Metro ProgressRing control defaults to a Minimum size of 60x60.

There is a property for the ProgressRing called "IsLarge", but even when it is set to "False" it seems to have no effect on being able to make to ProgressRing smaller than 60x60.

Obiviously changing the Height and Width properties do not affect this either.

Looking on GitHUb as the actual c# code for the ProgressRing, it looks like there are several properties to affect ellipse diameter, etc, but these properties are private properties, and can not be set from outside calls.

How can I make this smaller? Say 20x20 or 30x30?

In the below code I specify IsLarge=False, and set the size to 30x30, but it still defaults to 60x60.

<Window x:Class="WpfApplication3.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:Controls="clr-namespace:MahApps.Metro.Controls;assembly=MahApps.Metro"
        Title="MainWindow" Height="350" Width="525">
    <Window.Resources>
        <ResourceDictionary>
            <ResourceDictionary.MergedDictionaries>
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Colours.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Fonts.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Controls.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/Orange.xaml" />
                <ResourceDictionary Source="pack://application:,,,/MahApps.Metro;component/Styles/Accents/BaseLight.xaml" />
            </ResourceDictionary.MergedDictionaries>
        </ResourceDictionary>
    </Window.Resources>
         <Grid>
            <Controls:ProgressRing IsActive="True" IsLarge="False" Height="30" Width="30"></Controls:ProgressRing>
        </Grid>
</Window>

Below are snippets of code from the "ProgressRing.cs" file found on GitHub - MahApps.Metro

namespace MahApps.Metro.Controls
{
    [TemplateVisualState(Name = "Large", GroupName = "SizeStates")]
    [TemplateVisualState(Name = "Small", GroupName = "SizeStates")]
    [TemplateVisualState(Name = "Inactive", GroupName = "ActiveStates")]
    [TemplateVisualState(Name = "Active", GroupName = "ActiveStates")]
    public class ProgressRing : Control


        private void SetMaxSideLength(double width)
        {
            MaxSideLength = width <= 60 ? 60.0 : width;
        }

        private void SetEllipseDiameter(double width)
        {
            if (width <= 60)
            {
                EllipseDiameter = 6.0;
            }
            else
            {
                EllipseDiameter = width * 0.1 + 6;
            }
        }

        private void UpdateLargeState()
        {
            Action action;

            if (IsLarge)
                action = () => VisualStateManager.GoToState(this, "Large", true);
            else
                action = () => VisualStateManager.GoToState(this, "Small", true);

            if (_deferredActions != null)
                _deferredActions.Add(action);

            else
                action();
        }

EDIT:MainWindow.xaml

<Grid>
    <Controls:ProgressRing x:Name="PRing" IsLarge="False" MinHeight="15" MinWidth="15" Height="15" Width="15"></Controls:ProgressRing>
</Grid>

EDIT:MainWindow.xaml.cs

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
            PRing.EllipseDiameter = 5;
        }
    }

回答1:

You have to find a style for ProgressRing and set yourself the Width and Height. For me, the style is located at: MahApps.Metro master \ MahApps.Metro \ Themes \ ProgressRing.xaml:

<Style TargetType="{x:Type Controls:ProgressRing}">
    <Setter Property="Foreground" Value="{DynamicResource AccentColorBrush}"/>
    <Setter Property="IsHitTestVisible" Value="False"/>
    <Setter Property="HorizontalAlignment" Value="Center"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="MinHeight" Value="30"/>
    <Setter Property="MinWidth" Value="30"/>

...

By default, there are Width and Height of 60. As far as I understand, easy set Width and Height directly affects only the ellipses.

EDIT:

What would make the ring even smaller, you can play around with the parameters EllipseDiameter and EllipseOffset through code, because a XAML they will not be available (as private).

private void SetEllipseDiameter(double width)
{
    if (width <= 60)
    {
        EllipseDiameter = 3.0; // as default 6.0
    }
    else
    {
        EllipseDiameter = width * 0.1 + 6;
    }
}

private void SetEllipseOffset(double width)
{
    if (width <= 60)
    {
        EllipseOffset = new Thickness(0, 12, 0, 0); // as default 24
    }
    else
    {
        EllipseOffset = new Thickness(0, width * 0.4 + 12, 0, 0);
    }
}

EDIT2:

To set the diameter of the Ellipse can be done as follows. We do have properties EllipseDiameter setter public:

public double EllipseDiameter
{
    get 
    {
        return (double)GetValue(EllipseDiameterProperty); 
    }

    set // default as private
    {
        SetValue(EllipseDiameterProperty, value);
    }
}

In SetEllipseDiameter are checking on the size of the Ellipse, if the Width is less than 60 then set 6.0. We comment out.

private void SetEllipseDiameter(double width)
{
    //if (width <= 60)
    //{
    //    EllipseDiameter = 6.0;
    //}
    //else
    //{
    //    EllipseDiameter = width * 0.1 + 6;
    //}
 }

And in Style set the diameter of Ellipse like that:

<Setter Property="MinHeight" Value="30"/>
<Setter Property="MinWidth" Value="30"/>
<Setter Property="EllipseDiameter" Value="3.0" />

The same goes for EllipseOffset. He, too, at first private, and have check for a Width smaller than 60:

private void SetEllipseOffset(double width)
{
    // you can drop this check
    if (width <= 60)
    {
        EllipseOffset = new Thickness(0, 24, 0, 0); 
    }
    else
    {
        EllipseOffset = new Thickness(0, width * 0.4 + 24, 0, 0);
    }
}

Forging these operations with these parameters, you can configure the Width and Height of ProgressRing control.