You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何根据数值调整WPF Toolkit柱状图的柱体颜色与行高

解决方案

1. 重构数据模型

替换原有的KeyValuePair为自定义数据类,拆分标准工时与超出工时,方便后续绑定逻辑:

public class WorkHourItem : INotifyPropertyChanged
{
    private DateTime _date;
    private int _totalHours;
    private int _standardHours = 8; // 可根据实际需求调整标准工时

    public DateTime Date
    {
        get => _date;
        set { _date = value; OnPropertyChanged(); }
    }

    public int TotalHours
    {
        get => _totalHours;
        set 
        { 
            _totalHours = value; 
            OnPropertyChanged(); 
            OnPropertyChanged(nameof(OverHours)); 
            OnPropertyChanged(nameof(StandardHoursUsed)); 
        }
    }

    public int StandardHours
    {
        get => _standardHours;
        set 
        { 
            _standardHours = value; 
            OnPropertyChanged(); 
            OnPropertyChanged(nameof(OverHours)); 
            OnPropertyChanged(nameof(StandardHoursUsed)); 
        }
    }

    // 计算超出工时(小于0时取0)
    public int OverHours => Math.Max(0, TotalHours - StandardHours);
    // 计算标准内工时(大于标准工时取标准值)
    public int StandardHoursUsed => Math.Min(TotalHours, StandardHours);

    public event PropertyChangedEventHandler PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

2. 更新ViewModel

将集合替换为自定义数据类的ObservableCollection,适配新的数据模型:

private ObservableCollection<WorkHourItem> _myGraph;
public ObservableCollection<WorkHourItem> MyGraph
{
    get => _myGraph;
    set { _myGraph = value; OnPropertyChanged(); }
}

public ChartVM()
{
    MyGraph = new ObservableCollection<WorkHourItem>()
    {
        new WorkHourItem { Date = DateTime.Now, TotalHours = 8 },
        new WorkHourItem { Date = DateTime.Now.AddDays(1), TotalHours = 11 },
        new WorkHourItem { Date = DateTime.Now.AddDays(2), TotalHours = 7 },
        new WorkHourItem { Date = DateTime.Now.AddDays(3), TotalHours = 14 },
        new WorkHourItem { Date = DateTime.Now.AddDays(4), TotalHours = 5 },
    };
}

3. 创建值转换器

需要两个转换器实现动态逻辑:

工时转行高转换器

将工时占总工时的比例转为Grid的Star行高:

public class HourToRowHeightConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        if (value is int hours && parameter is int totalHours && totalHours > 0)
        {
            double ratio = (double)hours / totalHours;
            return new GridLength(ratio, GridUnitType.Star);
        }
        return GridLength.Auto;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

数值转可见性转换器

控制橙色超出部分的显示/隐藏(无超时则隐藏):

public class HourToVisibilityConverter : IValueConverter
{
    public object Convert(object value, Type targetType, object parameter, CultureInfo culture)
    {
        return value is int hours && hours > 0 ? Visibility.Visible : Visibility.Collapsed;
    }

    public object ConvertBack(object value, Type targetType, object parameter, CultureInfo culture)
    {
        throw new NotImplementedException();
    }
}

4. 修改XAML代码

在资源中引用转换器,更新ColumnSeries的DataPoint模板,实现动态行高和颜色显示:

<Window.Resources>
    <local:HourToRowHeightConverter x:Key="HourToRowHeightConverter"/>
    <local:HourToVisibilityConverter x:Key="HourToVisibilityConverter"/>
</Window.Resources>

<chartingToolkit:Chart Name="chart1"
                       Title="Availability"
                       VerticalAlignment="Stretch">
    <chartingToolkit:Chart.Series>
        <chartingToolkit:ColumnSeries ItemsSource="{Binding MyGraph}"
                                      IndependentValuePath="Date"
                                      DependentValuePath="TotalHours">
            <chartingToolkit:ColumnSeries.DataPointStyle>
                <Style TargetType="chartingToolkit:ColumnDataPoint">
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="chartingToolkit:ColumnDataPoint">
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <!-- 绑定超出工时的比例作为行高 -->
                                        <RowDefinition Height="{Binding OverHours, Converter={StaticResource HourToRowHeightConverter}, ConverterParameter={Binding TotalHours}}"/>
                                        <!-- 绑定标准内工时的比例作为行高 -->
                                        <RowDefinition Height="{Binding StandardHoursUsed, Converter={StaticResource HourToRowHeightConverter}, ConverterParameter={Binding TotalHours}}"/>
                                    </Grid.RowDefinitions>
                                    <!-- 超出部分:有超时才显示 -->
                                    <Rectangle Fill="Orange"
                                               Stroke="Black"
                                               Visibility="{Binding OverHours, Converter={StaticResource HourToVisibilityConverter}}"/>
                                    <!-- 标准内部分 -->
                                    <Rectangle Fill="Green" Grid.Row="1"/>
                                </Grid>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </chartingToolkit:ColumnSeries.DataPointStyle>
        </chartingToolkit:ColumnSeries>
    </chartingToolkit:Chart.Series>
</chartingToolkit:Chart>

核心逻辑说明

  • 数据模型拆分标准/超出工时,明确各部分数值;
  • 行高转换器根据工时占比动态分配Grid两行高度,实现柱体颜色区域的比例适配;
  • 可见性转换器确保无超时的柱体不显示橙色区域;
  • ColumnSeries绑定总工时,保证柱体整体高度与实际工时匹配。

内容的提问来源于stack exchange,提问作者Gokhan

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.22 16:39:57