XAML 将列表转换为控件列表

XAML convert a list to a list of controls

我正在使用 UI 来自 telerik 的 UWP 来绘制图表。 https://github.com/telerik/UI-For-UWP

我正在尝试数据绑定注释并动态显示它们。

我绑定了一个这样的注释:

查看

<chart:RadCartesianChart x:Name="OhlcChart" PaletteName="DefaultLightSelected" Grid.Row="1">
            <chart:RadCartesianChart.VerticalAxis>
                <chart:LinearAxis/>
            </chart:RadCartesianChart.VerticalAxis>
            <chart:RadCartesianChart.HorizontalAxis>
                <chart:DateTimeCategoricalAxis LabelFormat="{}{0,0:dd/MM}"/>
            </chart:RadCartesianChart.HorizontalAxis>
            <chart:RadCartesianChart.Annotations>
                <chart:CartesianCustomLineAnnotation
                            HorizontalFrom="{x:Bind ViewModel.Annotations[0].Date1}"
                            VerticalFrom="{x:Bind ViewModel.Annotations[0].Value1}"
                            HorizontalTo="{x:Bind ViewModel.Annotations[0].Date2}"
                            VerticalTo="{x:Bind ViewModel.Annotations[0].Value2}"
                            />

                    </chart:RadCartesianChart.Annotations>
            </chart:RadCartesianChart.Annotations>
</chart:RadCartesianChart>

查看模型

public class ChartViewModel : ViewModelBase
{
    public class DataItem 
    {
         public DateTime Date1 { get; set; }
         public double Value1 { get; set; }
         public DateTime Date2 { get; set; }
         public double Value2 { get; set; }
    }
    public DataItem [] Annotations { get; }
}

如何像这样绑定可枚举数量的注释:

public class ChartViewModel : ViewModelBase
{
    public class DataItem 
    {
         public DateTime Date1 { get; set; }
         public double Value1 { get; set; }
         public DateTime Date2 { get; set; }
         public double Value2 { get; set; }
    }
    public DataItem [] Annotations { get; }
}

RadCartesianChart.Annotations 没有像 ListView 和 GridView 那样的 ItemTemplate 属性。

我想绑定我的视图模型,使我的视图模型数组中的每个项目都有一个 CartesianCustomLineAnnotation

由此document可见,我们可以使用RadCartesianChart.AnnotationsProvider来实现绑定。但它只能在 WPF 中使用,不能在 UWP 中使用。所以如果要数据绑定注解,貌似只能在xaml或者code-behind中手动添加CartesianCustomLineAnnotation。

更新:

如果 ViewModel 实现了 INotifyProperty,您可以在代码隐藏中手动进行绑定。这会有点复杂。我使用 VerticalFrom 作为示例。

ChartViewModel.DataItem item1 = new ChartViewModel.DataItem();
item1.Value1 = 10;

CartesianCustomLineAnnotation c1 = new CartesianCustomLineAnnotation();
c1.Stroke = new SolidColorBrush(Colors.Red);
c1.StrokeThickness = 2;

Binding myBinding = new Binding();
myBinding.Source = item1;
myBinding.Path = new PropertyPath("Value1");
myBinding.Mode = BindingMode.OneWay;
BindingOperations.SetBinding(c1, CartesianCustomLineAnnotation.VerticalFromProperty, myBinding);

OhlcChart.Annotations.Add(c1);

我能够像这样解决我的问题

public class ViewModel : ViewModelBase
{
    public Angle[] Angles
    {
        get => _angles;
        set => SetProperty(ref _angles, value);
    }

    public class Angle
    {
        public DateTime Date1 { get; set; }
        public double Value1 { get; set; }
        public double Value2 { get; set; }
        public DateTime Date2 { get; set; }
    }
}

代码隐藏

public class ChartPage : Page
{
    private static readonly DependencyProperty AnnotationsProperty =
        DependencyProperty.RegisterAttached(
            "AnnotationsProperty",
            typeof(Angle[]),
            typeof(ChartPage),
            new PropertyMetadata(Array.Empty<Angle>(), OnAnnotationsChanged));

    public static void OnAnnotationsChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
    {
        var chart = (RadCartesianChart)d;
        var angles = e.NewValue as Angle[];
        chart.Annotations.Clear();
        if (angles == null || angles.Length == 0)
        {
            return;
        }

        angles
            .Select(x => new CartesianCustomLineAnnotation
            {
                HorizontalFrom = x.Date1,
                HorizontalTo = x.Date2,
                VerticalFrom = x.Value1,
                VerticalTo = x.Value2
            })
            .ToList()
            .ForEach(chart.Annotations.Add);
    }

    public ChartPage()
    {

        InitializeComponent();
        this.OhlcChart.SetBinding(AnnotationsProperty, new Binding
        {
            Path = new PropertyPath(nameof(ChartViewModel.Angles)),
            Mode = BindingMode.OneWay,
        });
    }
}

我希望这是正确的方法并且不会发生内存泄漏。