更新1
我发现在setter中的绑定在WinRT中不起作用。所以我从这个CodeProject article.
得到了一个帮助类所以我的绑定会是这样的。
应该工作,但不适合我。
<Setter Property="helper:SetterValueBindingHelper.PropertyBinding">
<Setter.Value>
<helper:SetterValueBindingHelper
Type="WinRTXamlToolkit.Controls.DataVisualization.Charting.LineDataPoint, WinRTXamlToolkit.Controls.DataVisualization, Version=1.0.0.0, Culture=neutral, PublicKeyToken=null"
Property="Background"
Binding="{Binding Color}"/>
</Setter.Value>
</Setter>
由于WinRT限制而无法正常工作
<Setter Property="Background" Value="{Binding Color}"/>
我收到ArgumentException - Unable to access DependencyProperty "Background" on type "LineDataPoint".
我的代码出了什么问题?
[ContentProperty(Name = "Values")]
public class SetterValueBindingHelper
{
/// <summary>
/// Optional type parameter used to specify the type of an attached
/// DependencyProperty as an assembly-qualified name, full name, or
/// short name.
/// </summary>
[SuppressMessage("Microsoft.Naming", "CA1721:PropertyNamesShouldNotMatchGetMethods",
Justification = "Unambiguous in XAML.")]
public string Type { get; set; }
/// <summary>
/// Property name for the normal/attached DependencyProperty on which
/// to set the Binding.
/// </summary>
public string Property { get; set; }
/// <summary>
/// Binding to set on the specified property.
/// </summary>
public Binding Binding { get; set; }
/// <summary>
/// Collection of SetterValueBindingHelper instances to apply to the
/// target element.
/// </summary>
/// <remarks>
/// Used when multiple Bindings need to be applied to the same element.
/// </remarks>
public Collection<SetterValueBindingHelper> Values
{
get
{
// Defer creating collection until needed
if (null == _values)
{
_values = new Collection<SetterValueBindingHelper>();
}
return _values;
}
}
private Collection<SetterValueBindingHelper> _values;
/// <summary>
/// Gets the value of the PropertyBinding attached DependencyProperty.
/// </summary>
/// <param name="element">Element for which to get the property.</param>
/// <returns>Value of PropertyBinding attached DependencyProperty.</returns>
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters",
Justification = "SetBinding is only available on FrameworkElement.")]
public static SetterValueBindingHelper GetPropertyBinding(FrameworkElement element)
{
if (null == element)
{
throw new ArgumentNullException("element");
}
return (SetterValueBindingHelper)element.GetValue(PropertyBindingProperty);
}
/// <summary>
/// Sets the value of the PropertyBinding attached DependencyProperty.
/// </summary>
/// <param name="element">Element on which to set the property.</param>
/// <param name="value">Value forPropertyBinding attached DependencyProperty.</param>
[SuppressMessage("Microsoft.Design", "CA1011:ConsiderPassingBaseTypesAsParameters",
Justification = "SetBinding is only available on FrameworkElement.")]
public static void SetPropertyBinding(FrameworkElement element, SetterValueBindingHelper value)
{
if (null == element)
{
throw new ArgumentNullException("element");
}
element.SetValue(PropertyBindingProperty, value);
}
/// <summary>
/// PropertyBinding attached DependencyProperty.
/// </summary>
public static readonly DependencyProperty PropertyBindingProperty =
DependencyProperty.RegisterAttached(
"PropertyBinding",
typeof(SetterValueBindingHelper),
typeof(SetterValueBindingHelper),
new PropertyMetadata(null, OnPropertyBindingPropertyChanged));
/// <summary>
/// Change handler for the PropertyBinding attached DependencyProperty.
/// </summary>
/// <param name="d">Object on which the property was changed.</param>
/// <param name="e">Property change arguments.</param>
private static void OnPropertyBindingPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
// Get/validate parameters
var element = (FrameworkElement)d;
var item = (SetterValueBindingHelper)(e.NewValue);
if ((null == item.Values) || (0 == item.Values.Count))
{
// No children; apply the relevant binding
ApplyBinding(element, item);
}
else
{
// Apply the bindings of each child
foreach (var child in item.Values)
{
if ((null != item.Property) || (null != item.Binding))
{
throw new ArgumentException(
"A SetterValueBindingHelper with Values may not have its Property or Binding set.");
}
if (0 != child.Values.Count)
{
throw new ArgumentException(
"Values of a SetterValueBindingHelper may not have Values themselves.");
}
ApplyBinding(element, child);
}
}
}
/// <summary>
/// Applies the Binding represented by the SetterValueBindingHelper.
/// </summary>
/// <param name="element">Element to apply the Binding to.</param>
/// <param name="item">SetterValueBindingHelper representing the Binding.</param>
private static void ApplyBinding(FrameworkElement element, SetterValueBindingHelper item)
{
if ((null == item.Property) || (null == item.Binding))
{
throw new ArgumentException(
"SetterValueBindingHelper's Property and Binding must both be set to non-null values.");
}
// Get the type on which to set the Binding
Type type = null;
TypeInfo typeInfo = null;
if (null == item.Type)
{
// No type specified; setting for the specified element
type = element.GetType();
typeInfo = type.GetTypeInfo();
}
else
{
// Try to get the type from the type system
type = System.Type.GetType(item.Type);
if (null == type)
{
// Search for the type in the list of assemblies
foreach (var assembly in AssembliesToSearch)
{
// Match on short or full name
typeInfo = assembly.DefinedTypes
.Where(t => (t.FullName == item.Type) || (t.Name == item.Type))
.FirstOrDefault();
if (null != typeInfo)
{
// Found; done searching
break;
}
}
if (null == typeInfo)
{
// Unable to find the requested type anywhere
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
"Unable to access type \"{0}\". Try using an assembly qualified type name.",
item.Type));
}
}
else
{
typeInfo = type.GetTypeInfo();
}
}
// Get the DependencyProperty for which to set the Binding
DependencyProperty property = null;
var field = typeInfo.GetDeclaredProperty(item.Property + "Property"); // type.GetRuntimeField(item.Property + "Property");
if (null != field)
{
property = field.GetValue(null) as DependencyProperty;
}
if (null == property)
{
// Unable to find the requsted property
throw new ArgumentException(string.Format(CultureInfo.CurrentCulture,
"Unable to access DependencyProperty \"{0}\" on type \"{1}\".",
item.Property, type.Name));
}
// Set the specified Binding on the specified property
element.SetBinding(property, item.Binding);
}
/// <summary>
/// Returns a stream of assemblies to search for the provided type name.
/// </summary>
private static IEnumerable<Assembly> AssembliesToSearch
{
get
{
// Start with the System.Windows assembly (home of all core controls)
yield return typeof(Control).GetTypeInfo().Assembly;
}
}
}
我需要在WinRT XAML Toolkit的帮助下在图表中创建n
行系列。我想使用自定义样式的线条颜色,自定义数据点样式&amp;自定义工具提示。如果我有固定数量的系列,我会这样做。
<charting:Chart x:Name="LineChart" Title="Line Chart" Margin="70,0">
<charting:LineSeries
Title="Population 1"
IndependentValueBinding="{Binding Name}"
DependentValueBinding="{Binding Value}"
IsSelectionEnabled="True">
<charting:LineSeries.DataPointStyle>
<Style TargetType="charting:LineDataPoint">
<Setter Property="Width" Value="17" />
<Setter Property="Height" Value="17" />
<Setter Property="Background" Value="Lime"/>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="charting:LineDataPoint">
<Grid>
<ToolTipService.ToolTip>
<ContentControl>
<TextBlock TextAlignment="Center">
<Run Text="{Binding SeriesName}" />
<LineBreak />
<Run Text="{Binding Value,Converter={StaticResource MyConverter},ConverterParameter=TEST}" />
</TextBlock>
</ContentControl>
</ToolTipService.ToolTip>
<Ellipse Fill="Lime" Stroke="Lime" StrokeThickness="3" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</charting:LineSeries.DataPointStyle>
</charting:LineSeries>
</charting:Chart>
现在这里是工具提示内容&amp;线条的颜色和数据点将是动态的,即颜色将是随机的,工具提示内容将来自绑定。现在要创建动态系列,我尝试了代码隐藏方法,但是在将代码隐藏在代码背后的工具提示内容时遇到了问题。看看我背后的代码方法。
<charting:Chart x:Name="LineChart" Title="Line Chart" Margin="70,0" />
protected override void OnNavigatedTo(NavigationEventArgs e)
{
LineSeries line;
GenerateColors(20); //suppose I need to create 20 line series, that is dynamic value.
for (int i = 0; i < 20; i++)
{
line = new LineSeries();
line.Title = string.Format("Line [{0}]", i.ToString());
line.IndependentValueBinding = GetBinding("Name");
line.DependentValueBinding = GetBinding("Value");
line.ItemsSource = GetItems();
line.DataPointStyle = GetDataPointStyle(i);
this.LineChart.Series.Add(line);
}
}
private List<NameValueItem> GetItems()
{
List<NameValueItem> items = new List<NameValueItem>();
items.Add(new NameValueItem { Name = "Test1", Value = _random.Next(10, 100) });
items.Add(new NameValueItem { Name = "Test2", Value = _random.Next(10, 100) });
items.Add(new NameValueItem { Name = "Test3", Value = _random.Next(10, 100) });
items.Add(new NameValueItem { Name = "Test4", Value = _random.Next(10, 100) });
items.Add(new NameValueItem { Name = "Test5", Value = _random.Next(10, 100) });
return items;
}
private Style GetDataPointStyle(int ColorIndex)
{
Style style = new Style();
style.TargetType = typeof(LineDataPoint);
style.Setters.Add(new Setter(LineDataPoint.WidthProperty, 17));
style.Setters.Add(new Setter(LineDataPoint.HeightProperty, 17));
style.Setters.Add(new Setter(LineDataPoint.BackgroundProperty, GetColorBrush(ColorIndex)));
return style;
}
我还尝试在xaml中创建全局样式的数据点并绑定颜色,但是当我这样做时,线条没有颜色,只有点得到颜色。这种方法如下。
<Page.Resources>
<converter:MyConverter x:Key="MyConverter" />
<Style TargetType="charting:LineDataPoint" x:Key="MyDataPointStyle">
<Setter Property="Width" Value="17" />
<Setter Property="Height" Value="17" />
<Setter Property="Background" Value="{Binding Color}"/>
<!-- ABOVE BINDING IS NOT WORKING, IF I PASS HARD CODED VALUE IT'S GETTING -->
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="charting:LineDataPoint">
<Grid>
<ToolTipService.ToolTip>
<ContentControl>
<TextBlock TextAlignment="Center">
<Run Text="{Binding SeriesName}" />
<LineBreak />
<Run Text="{Binding Value,Converter={StaticResource MyConverter},ConverterParameter=TEST}" />
</TextBlock>
</ContentControl>
</ToolTipService.ToolTip>
<Ellipse Fill="{Binding Color}" Stroke="{Binding Color}" StrokeThickness="3" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Page.Resources>
protected override void OnNavigatedTo(NavigationEventArgs e)
{
LineSeries line;
GenerateColors(20); //suppose I need to create 20 line series, that is dynamic value.
for (int i = 0; i < 20; i++)
{
line = new LineSeries();
line.Title = string.Format("Line [{0}]", i.ToString());
line.IndependentValueBinding = GetBinding("Name");
line.DependentValueBinding = GetBinding("Value");
line.ItemsSource = GetItems();
//line.DataPointStyle = GetDataPointStyle(i);
line.DataPointStyle = this.Resources["MyDataPointStyle"] as Style;
this.LineChart.Series.Add(line);
}
}
答案 0 :(得分:0)
检查是否按照我在评论中提到的将绑定属性所有者类型更改为Control,如果它不起作用 - 请查看LineDataPoint
的模板 - 它有以下部分:
<Ellipse
Stroke="{TemplateBinding BorderBrush}"
Fill="{TemplateBinding Background}" />
您可以将TemplateBinding
更改为从您的数据获取画笔的常规Binding
,它应该有效。您可能希望使用LineSeries
样式执行类似的操作来为线条着色。
<Polyline
Points="{TemplateBinding Points}"
Stroke="{TemplateBinding Background}"
Style="{TemplateBinding PolylineStyle}" />