Blitzregn_Baby
Blitzregn_Baby

Reputation: 29

LinearGradientBrush not working as intended WPF

SOLVED. See comment by Rekshino

I heart that is supposed to represent hitpoints for an Initiative Tracker for tabletop games. The heart only works as intended on my computer, two different machines shows different results. When I run the program on a different machine, the heart stays red no matter what the hitpoints are.

This is what it is supposed to look like, and how it looks on my machine:

enter image description here

<DataGridTemplateColumn>
    <DataGridTemplateColumn.CellTemplate>
        <DataTemplate>
            <Canvas Width="20" Height="20" HorizontalAlignment="Center" VerticalAlignment="Center">

                <Path>
                    <Path.Style>
                        <Style TargetType="Path">
                            <Style.Triggers>
                                <MultiDataTrigger>
                                    <MultiDataTrigger.Conditions>
                                        <Condition Binding="{Binding Path=IsAlive}" Value="true"/>
                                        <Condition Binding="{Binding Path=IsConscious}" Value="true"/>
                                        <Condition Binding="{Binding Path=IsStable}" Value="true"/>
                                     </MultiDataTrigger.Conditions>
                                     <MultiDataTrigger.Setters>

                                         <Setter Property="HorizontalAlignment" Value="Left"/>
                                         <Setter Property="VerticalAlignment" Value="Top"/>
                                         <Setter Property="StrokeThickness" Value="2"/>
                                         <Setter Property="Stroke" Value="Black"/>
                                         <Setter Property="Height" Value="20"/>
                                         <Setter Property="Width" Value="20"/>
                                         <Setter Property="Data" Value="M45.445,12.4445 C45.278001,4.2777179 40.097263,0.5000003 
                                                            33.5005,0.5 28.965223,0.5000003 25.020309,3.0276406 22.997637,6.7510427 L22.9725,6.8001207 
                                                            22.947363,6.7510427 C20.92469,3.0276406 16.979776,0.5000003 12.4445,0.5 5.8477349,0.5000003 
                                                            0.72517072,5.8515793 0.5,12.4445 0.278,18.944584 22.997637,37.611504 22.997637,37.611504 
                                                            22.997637,37.611504 45.611998,20.611283 45.445,12.4445 z"/>
                                         <Setter Property="Stretch" Value="Fill"/>
                                     </MultiDataTrigger.Setters>
                                 </MultiDataTrigger>
                             </Style.Triggers>
                         </Style>
                     </Path.Style>
                     <!--Heartfilling control-->
                     <Path.Fill>
                         <LinearGradientBrush StartPoint="{Binding GradientFillString}">
                             <GradientStop Color="Black"/>
                             <GradientStop Color="Red" Offset="0"/>
                         </LinearGradientBrush>
                      </Path.Fill>
                  </Path>

The GradientFillString is a ratio between current hit points and max hit points in the format: "1 " + Convert.ToString(1 - ratio)

In the code i omitted several multidatatriggers that will manipulate the canvas in different ways that I believe is not specifically relevant to this problem. Those will trigger depending on the different states of the characters.

UPDATE. Attempting MCVE

CharacterMinimal.cs

using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace MCVE
{
    public class CharacterMinimal
    {
        public int MaxHealth { get; set; }
        public int CurrentHP { get; set; }
        public bool IsAlive { get; set; }

        public CharacterMinimal()
        {
            IsAlive = true;
        }
        public string GradientFillString
        {
            get
            {
                if (MaxHealth > 0)
                {
                    decimal calc = Convert.ToDecimal(CurrentHP) / Convert.ToDecimal(MaxHealth);
                    return "1 " + Convert.ToString(1 - calc);
                }
                else
                {
                    return "1 " + "1";
                }

            }
        }
    }

}

MainWindow.xaml

<Window x:Class="MCVE.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:MCVE"
        mc:Ignorable="d"
        DataContext="{Binding RelativeSource={RelativeSource Self}}"
        Title="MainWindow" Height="450" Width="800">
    <Grid x:Name="Grid1">
        <DataGrid ItemsSource="{Binding}" AutoGenerateColumns="False">
            <DataGrid.Columns>
                <!--Status Image / path-->
                <DataGridTemplateColumn>
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <Canvas Width="20" Height="20" HorizontalAlignment="Center" VerticalAlignment="Center">

                                <Path>
                                    <Path.Style>
                                        <Style TargetType="Path">
                                            <Style.Triggers>
                                                <MultiDataTrigger>
                                                    <MultiDataTrigger.Conditions>
                                                        <Condition Binding="{Binding Path=IsAlive}" Value="true"/>

                                                    </MultiDataTrigger.Conditions>
                                                    <MultiDataTrigger.Setters>

                                                        <Setter Property="HorizontalAlignment" Value="Left"/>
                                                        <Setter Property="VerticalAlignment" Value="Top"/>
                                                        <Setter Property="StrokeThickness" Value="2"/>
                                                        <Setter Property="Stroke" Value="Black"/>
                                                        <Setter Property="Height" Value="20"/>
                                                        <Setter Property="Width" Value="20"/>
                                                        <Setter Property="Data" Value="M45.445,12.4445 C45.278001,4.2777179 40.097263,0.5000003 
                                                                33.5005,0.5 28.965223,0.5000003 25.020309,3.0276406 22.997637,6.7510427 L22.9725,6.8001207 
                                                                22.947363,6.7510427 C20.92469,3.0276406 16.979776,0.5000003 12.4445,0.5 5.8477349,0.5000003 
                                                                0.72517072,5.8515793 0.5,12.4445 0.278,18.944584 22.997637,37.611504 22.997637,37.611504 
                                                                22.997637,37.611504 45.611998,20.611283 45.445,12.4445 z"/>
                                                        <Setter Property="Stretch" Value="Fill"/>
                                                    </MultiDataTrigger.Setters>
                                                </MultiDataTrigger>
                                            </Style.Triggers>
                                        </Style>
                                    </Path.Style>
                                    <!--Heartfilling control-->
                                    <Path.Fill>
                                        <LinearGradientBrush StartPoint="{Binding GradientFillString}">
                                            <GradientStop Color="Black"/>
                                            <GradientStop Color="Red" Offset="0"/>
                                        </LinearGradientBrush>
                                    </Path.Fill>
                                </Path>
                            </Canvas>
                        </DataTemplate>

                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Binding="{Binding MaxHealth}">
                </DataGridTextColumn>
            </DataGrid.Columns>

        </DataGrid>
    </Grid>
</Window>

MainWindow.xaml.cs

using System.Collections.Generic;
using System.Windows;

namespace MCVE
{
    public partial class MainWindow : Window
    {

        public MainWindow()
        {
            InitializeComponent();
            List<CharacterMinimal> population = new List<CharacterMinimal> {
                    new CharacterMinimal(){MaxHealth = 20, CurrentHP = 10},
                    new CharacterMinimal(){MaxHealth = 30, CurrentHP = 30},
                    new CharacterMinimal(){MaxHealth = 10, CurrentHP = 2}
                };
            Grid1.DataContext = population;
        }
    }
}

Upvotes: 0

Views: 265

Answers (1)

Rekshino
Rekshino

Reputation: 7325

You do compound a value for LinearGradientBrush.StartPoint in VewModel and the content for it is amongst other things a decimal number, e.g. 0.5. You get this number by Convert.ToString(), the decimal separator in this number is dependent on Windows settings, this is why on some PCs it doesn't work.

WindowsSetting

to solve the issue you could use the overloading Convert.ToString(decimal value, IFormatProvider provider) or just replace , with .:

Convert.ToString(1 - calc).Replace(",", ".")

Upvotes: 1

Related Questions