我通过命名空间使用WPF Charting ToolKit:
xmlns:ChartingToolkit="clr-namespace:System.Windows.Controls.DataVisualization.Charting;assembly=System.Windows.Controls.DataVisualization.Toolkit"
xmlns:VisualizationToolkit="clr-namespace:System.Windows.Controls.DataVisualization;assembly=System.Windows.Controls.DataVisualization.Toolkit"
我有一个图表控件,每次Lineseries
绘图时我会生成一个随机颜色。我删除了数据点标记并使用以下样式着色
<Style x:Key="LineDataPointStyle"
TargetType="ChartingToolkit:LineDataPoint">
<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>
LineSeries
是通过
<ChartingToolkit:LineSeries Title="{Binding DisplayName}"
AnimationSequence="FirstToLast"
SnapsToDevicePixels="True"
DataPointStyle="{StaticResource LineDataPointStyle}"
ItemsSource="{Binding Data}"
IndependentValueBinding="{Binding X}"
DependentValueBinding="{Binding Y}"/>
现在,这样可以正常工作,但图例标记显示的颜色与我为LineSeries
生成的随机颜色不同。我想为LineSeries
和Lineseries
本身的图例项目显示相同的颜色。所以,我将传说项目设置为如下
<Style x:Key="TestSuiteLegendItemStyle"
TargetType="{x:Type ChartingToolkit:LegendItem}">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ChartingToolkit:LegendItem}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel Orientation="Horizontal">
<Rectangle Width="8"
Height="8"
Fill="{Binding Background}"
Stroke="{Binding BorderBrush}"
StrokeThickness="1" Margin="0,0,3,0" />
<VisualizationToolkit:Title Content="{TemplateBinding Content}" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
我的问题是我该怎样绑定&#39; Rectangle.Fill
样式中的TestSuiteLegendItemStyle
,以便与上面定义的LineSeries
设置的LineDataPointStyle
颜色相同? *
感谢您的时间。
编辑。我尝试设置一个DependencyProperty
,其中包含我的情节的Background
颜色,如下所示
<Style x:Key="LineDataPointStyle"
TargetType="ChartingToolkit:LineDataPoint">
...
<Setter Property="Background"
Value="{Binding RelativeSource={RelativeSource Self},
Converter={StaticResource ColorBrushConverter}}"/>
...
</Style>
我已经修改了转换器(标记为),以便我可以存储随机生成的背景颜色,然后在我的图例中使用它
public class ColorToBrushConverter : IValueConverter
{
public object Convert(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
Brush b = new SolidColorBrush(Utils.GenerateRandomColor());
MultiChartExtensions.BackgroundBrushProperty = b; <= how to set the dependency property?
return b;
}
public object ConvertBack(object value, Type targetType,
object parameter, System.Globalization.CultureInfo culture)
{
throw new NotImplementedException();
}
}
其中依赖属性(DP)定义为
public static readonly DependencyProperty BackgroundBrushProperty;
public static void SetBackgroundBrush(DependencyObject DepObject, Brush value)
{
DepObject.SetValue(BackgroundBrushProperty, value);
}
public static Brush GetBackgroundBrush(DependencyObject DepObject)
{
return (Brush)DepObject.GetValue(BackgroundBrushProperty);
}
然后我会通过此DP通过
设置图例背景<Style x:Key="TestSuiteLegendItemStyle"
TargetType="{x:Type ChartingToolkit:LegendItem}">
<Setter Property="IsTabStop" Value="False"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ChartingToolkit:LegendItem}">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<StackPanel Orientation="Horizontal">
<Rectangle Width="8"
Height="8"
Fill="{Binding MultiChart:MultiChartExtensions.BackgroundBrushProperty}"
Stroke="{Binding BorderBrush}"
StrokeThickness="1" Margin="0,0,3,0" />
<VisualizationToolkit:Title Content="{TemplateBinding Content}" />
</StackPanel>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
对此有任何帮助将不胜感激......
答案 0 :(得分:5)
<强> Part I. Binding in ControlTemplate
强>
如果要在ControlTemplate
中使用 Binding ,则应使用以下构造:
<ControlTemplate TargetType="{x:Type SomeControl}">
<Rectangle Fill="{TemplateBinding Background}" />
引自MSDN
:
TemplateBinding
是模板场景绑定的优化形式,类似于使用{Binding RelativeSource={RelativeSource TemplatedParent}}.
构建的绑定
Notes about using TemplateBinding
TemplateBinding
在模板外或VisualTree属性之外不起作用,因此您甚至无法在模板的触发器中使用TemplateBinding。此外,当应用于Freezable时,TemplateBinding不起作用(主要是出于人为原因),例如 - 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
删除此绑定,或使用其他属性(例如Tag
或附加依赖项属性)来绑定背景颜色。< / p>
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
此处针对Rectangle
,设置两种颜色:默认为Rectangle
,标记为Border
。我认为这不是一个好的解决方案,这就是原因:
如果Border和Rectangle需要设置不同的值,例如:Background,BorderThickness,BorderBrush等,则Tag
是不够的。
使用一个名称属性必须明确其目的,一个名称“标记”我们什么都没说。
这些缺点可以归结为我们应该找到一个替代方案,作为替代方案,我使用带有附加依赖属性的扩展类。
Extender class 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
<强> 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
。我尝试在Binding和属性声明Mode=TwoWay
中设置UpdateSourceTrigger=PropertyChanged
,GetBindingExpression().UpdateTarget()
,但它没用。
请注意,对于属性设置 new 值,并且模板中的通知不是,该属性已更新。也许我错了,你会工作,或者可能是专门制作的,例如为了避免内存泄漏。
在任何情况下,最好不要直接更新依赖项属性,并将Model
的属性绑定到它,并在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}" />
其中RectBackground
和RectBorderBrush
实现了INotifyPropertyChanged
接口。
在这种情况下,请不要使用依赖项属性,并使用DataTemplate
作为控件。 DataTemplate
非常适合MVVM,非常灵活和动态。
例如,使用DataTemplate
,您可以看到我的答案:
Make (create) reusable dynamic Views
One ViewModel for UserControl and Window or separate ViewModels
答案 1 :(得分:1)
在LineSeries控件上设置x:Name
:
<ChartingToolkit:LineSeries x:Name="lineSeries"/>
然后,您可以使用TestSuiteLegendItemStyle
ElementName
<Rectangle Fill="{Binding Background, ElementName=lineSeries}"/>