gpt4 book ai didi

c# - 更改 WPF 图表工具包图例中显示的颜色

转载 作者:行者123 更新时间:2023-11-30 12:28:34 26 4
gpt4 key购买 nike

我有以下样式,它删除数据点并为我的线系列图随机生成线条颜色

<Style x:Key="LineDataPointStyle" 
TargetType="ChartingToolkit:LineDataPoint">
<Setter Property="Foreground" Value="DarkGreen"/>
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Width" Value="NaN"/>
<Setter Property="Height" Value="NaN"/>
<Setter Property="Background"
Value="{Binding RelativeSource={RelativeSource Self},
Converter={StaticResource ColorBrushConverter}}"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ChartingToolkit:LineDataPoint">
<Grid x:Name="Root" Opacity="0"/>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>

转换器在哪里:
public class ColorToBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
return new SolidColorBrush(Utils.GenerateRandomColor());
}

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

这会以随机颜色生成线条,但图例是不同的颜色;要么由库本身自动生成,要么它也通过样式模板调用我的转换器。

Shown

如何让图例打印正确的颜色?

最佳答案

注:是Killercam问题的答案, 已被问到 here .这个问题的答案特别适合他的赏金,所以应他的要求,我在这里发布。

在这个答案中,Button控件用于演示如何使用模板。

Part I. Binding in ControlTemplate

如果你想在 ControlTemplate 中使用绑定(bind),您应该使用以下构造:

<ControlTemplate TargetType="{x:Type SomeControl}">
<Rectangle Fill="{TemplateBinding Background}" />

引自 MSDN :

A TemplateBinding is an optimized form of a Binding for template scenarios, analogous to a Binding constructed with {Binding RelativeSource={RelativeSource TemplatedParent}}.


Notes about using TemplateBinding TemplateBinding在模板之外或其 VisualTree 属性之外不起作用,因此您甚至不能在模板的触发器中使用 TemplateBinding。此外,TemplateBinding 在应用于 Freezable 时不起作用(主要是人为原因),例如 - VisualBrush .在这种情况下,可以像这样使用 Binding:
<FreezableControl Property="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Background}" />

此外,您始终可以使用 TemplateBinding 的替代方法:
<Rectangle Fill="{Binding RelativeSource={RelativeSource TemplatedParent},
Path=Background}" />

作为另一种可能性,您还可以尝试以下方法:
<Rectangle Fill="{Binding Background, 
RelativeSource={RelativeSource AncestorType={x:Type SomeControl}},
Path=Background}" />

Part II. Notes about your version

在您的情况下,这可能会导致 ControlTemplate 中的名称冲突。 ,因为您已经在使用 Binding 背景用于 Border。因此,将其删除此绑定(bind)为 Border ,或使用其他属性,例如 Tag或附加的用于绑定(bind)背景颜色的依赖属性。
Example of using
而是 ChartingToolkit控制,作为基础 Button控制,因为更容易展示这种风格的想法。

Solution 1: using Tag
<Window.Resources>
<Style x:Key="TestButtonStyle" TargetType="{x:Type Button}">
<Setter Property="BorderThickness" Value="0" />
<Setter Property="IsTabStop" Value="False" />

<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Button}">
<!-- Here we are set Tag for Border Background -->
<Border Background="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Tag}"
BorderThickness="{TemplateBinding BorderThickness}">

<Grid>
<Rectangle Width="24"
Height="24"
Fill="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=Background}"
Stroke="{TemplateBinding BorderBrush}" />

<ContentPresenter Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>

<Grid>
<Button Name="TestButton"
Style="{StaticResource TestButtonStyle}"
Content="Test"
HorizontalContentAlignment="Center"
VerticalContentAlignment="Center"
Tag="Green"
Background="Aquamarine"
Width="100"
Height="100" />
</Grid>
Output
enter image description here

这里为 Rectangle ,设置两种颜色:默认为 Rectangle , 在标签中为 Border .我认为这不是一个好的解决方案,原因如下:
  • 如果一个Border和Rectangle需要设置不同的值,比如:Background、BorderThickness、BorderBrush等一个Tag是不足够的。
  • 用一个名字属性必须明确它的用途,一个名字“标签”我们就无话可说了。

  • 对于这些缺点,可以得出结论,我们应该找到一个替代方案,作为替代方案,我使用带有附加依赖属性的扩展器类。

    扩展类 ButtonExt.cs
    public static class ButtonExt
    {
    #region RectangleBackground Property

    public static readonly DependencyProperty RectangleBackgroundProperty;

    public static void SetRectangleBackground(DependencyObject DepObject, Brush value)
    {
    DepObject.SetValue(RectangleBackgroundProperty, value);
    }

    public static Brush GetRectangleBackground(DependencyObject DepObject)
    {
    return (Brush)DepObject.GetValue(RectangleBackgroundProperty);
    }

    #endregion

    #region RectangleBorderBrush Property

    public static readonly DependencyProperty RectangleBorderBrushProperty;

    public static void SetRectangleBorderBrush(DependencyObject DepObject, Brush value)
    {
    DepObject.SetValue(RectangleBorderBrushProperty, value);
    }

    public static Brush GetRectangleBorderBrush(DependencyObject DepObject)
    {
    return (Brush)DepObject.GetValue(RectangleBorderBrushProperty);
    }

    #endregion

    #region Button Constructor

    static ButtonExt()
    {
    #region RectangleBackground

    PropertyMetadata BrushPropertyMetadata = new PropertyMetadata(Brushes.Transparent);

    RectangleBackgroundProperty = DependencyProperty.RegisterAttached("RectangleBackground",
    typeof(Brush),
    typeof(ButtonExt),
    BrushPropertyMetadata);

    #endregion

    #region RectangleBorderBrush

    RectangleBorderBrushProperty = DependencyProperty.RegisterAttached("RectangleBorderBrush",
    typeof(Brush),
    typeof(ButtonExt),
    BrushPropertyMetadata);

    #endregion
    }

    #endregion
    }
    MainWindow.xaml
    <Window.Resources>
    <Style x:Key="TestButtonExtensionStyle" TargetType="{x:Type Button}">
    <Setter Property="Width" Value="80" />
    <Setter Property="Height" Value="80" />
    <Setter Property="Background" Value="Green" />
    <Setter Property="BorderBrush" Value="Pink" />
    <Setter Property="BorderThickness" Value="4" />

    <Setter Property="Template">
    <Setter.Value>
    <ControlTemplate TargetType="{x:Type Button}">
    <Border Background="{TemplateBinding Background}"
    BorderBrush="{TemplateBinding BorderBrush}"
    BorderThickness="{TemplateBinding BorderThickness}">

    <Grid>
    <Rectangle Fill="{TemplateBinding PropertiesExtension:ButtonExt.RectangleBackground}"
    Stroke="{TemplateBinding PropertiesExtension:ButtonExt.RectangleBorderBrush}"
    Width="30"
    Height="30" />

    <ContentPresenter Content="{TemplateBinding Content}"
    HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
    VerticalAlignment="{TemplateBinding VerticalContentAlignment}" />
    </Grid>
    </Border>
    </ControlTemplate>
    </Setter.Value>
    </Setter>
    </Style>
    </Window.Resources>

    <Grid>
    <Button Style="{StaticResource TestButtonExtensionStyle}"
    PropertiesExtension:ButtonExt.RectangleBackground="Aquamarine"
    PropertiesExtension:ButtonExt.RectangleBorderBrush="Black"
    Content="Test" />
    </Grid>
    Output
    enter image description here

    Part III. Setting values for dependency properties

    当你创建和注册你附加的依赖属性时,你必须声明 Set 和 Get 方法来和他一起工作:
    public static void SetRectangleBackground(DependencyObject DepObject, Brush value)
    {
    DepObject.SetValue(RectangleBackgroundProperty, value);
    }

    public static Brush GetRectangleBackground(DependencyObject DepObject)
    {
    return (Brush)DepObject.GetValue(RectangleBackgroundProperty);
    }

    然后与他们合作如下:
    Set
    ButtonExt.SetRectangleBackground(MyButton, Brushes.Red);
    Get
    Brush MyBrush = ButtonExt.GetRectangleBackground(MyButton);

    但在我们的例子中,它并不是那么简单。当我使用附加的依赖属性时,更新值的问题都没有。但在我们的例子中,该属性在模板中,而在我的例子中,没有更新 Button .我试图设置 Mode=TwoWay , UpdateSourceTrigger=PropertyChanged ,在绑定(bind)和属性声明中, GetBindingExpression().UpdateTarget() ,但没用。

    请注意,对于设置新值的属性,并且没有来自模板的通知,该属性已被更新。也许我错了,你会工作,或者它是专门制作的,例如为了避免内存泄漏。

    无论如何,最好不要直接更新依赖属性,并将 Model 的属性绑定(bind)到它。在 ViewModel设置值。

    例子:
    <Button Style="{StaticResource TestButtonExtensionStyle}"
    adp:ButtonExt.RectangleBackground="{Binding Path=Model.RectBackground,
    Mode=TwoWay,
    UpdateSourceTrigger=PropertyChanged}"
    adp:ButtonExt.RectangleBorderBrush="{Binding Path=Model.RectBorderBrush,
    Mode=TwoWay,
    UpdateSourceTrigger=PropertyChanged}" />

    在哪里 RectBackgroundRectBorderBrush实现 INotifyPropertyChanged界面。

    在这种情况下,作为替代方案,不要使用依赖属性并使用 DataTemplate为控制。 DataTemplate MVVM 的理想选择,非常灵活和动态。

    例如,使用 DataTemplate ,你可以看到我的答案:

    Make (create) reusable dynamic Views

    One ViewModel for UserControl and Window or separate ViewModels

    关于c# - 更改 WPF 图表工具包图例中显示的颜色,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21293363/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com