未评估嵌套 XAML WPF 中的绑定

Binding in nested XAML WPF not evaluated

我有一个嵌套的 WPF 视图,我在其中通过依赖属性将对象传递到内层。

我的外 XAML 层将数据传递到 RetentionChartControl.ChartParams:

<local:RetentionChartControl ChartParams="{Binding PeakRow.Chartparams[0], RelativeSource={RelativeSource AncestorType={x:Type local:PeakrowChartGroupControl}}}"></local:RetentionChartControl>

在我的最内层我有以下XAML代码:

<UserControl x:Class="DryLab.Peakmovement.RetentionChartControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:local="clr-namespace:DryLab.Peakmovement" 
             xmlns:lvc="clr-namespace:LiveCharts.Wpf;assembly=LiveCharts.Wpf"
             mc:Ignorable="d"
             x:Name="uc"
             d:DesignHeight="450" d:DesignWidth="800">
   
    
    <Grid>
        <lvc:CartesianChart x:Name="cc" Series="{Binding ChartParams.Seriescollection, RelativeSource={RelativeSource AncestorType={x:Type local:RetentionChartControl}}}" >
            <lvc:CartesianChart.DataTooltip>
                <lvc:DefaultTooltip SelectionMode="OnlySender" />
            </lvc:CartesianChart.DataTooltip>
            <lvc:CartesianChart.AxisY>
                <lvc:Axis  Foreground="Black" Title="{Binding ChartParams.TitleAxY, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type local:RetentionChartControl}} }" LabelFormatter="{Binding ChartParams.Formatter, RelativeSource={RelativeSource AncestorType={x:Type local:RetentionChartControl}}}">
                </lvc:Axis>
            </lvc:CartesianChart.AxisY>
            <lvc:CartesianChart.AxisX>
                <lvc:Axis  Foreground="Black" Title="{Binding ChartParams.TitleAxX, RelativeSource={RelativeSource AncestorType={x:Type local:RetentionChartControl}}}" Labels="{Binding ChartParams.Labels, RelativeSource={RelativeSource AncestorType={x:Type local:RetentionChartControl}} }"></lvc:Axis>
            </lvc:CartesianChart.AxisX>
        </lvc:CartesianChart>
    </Grid>
</UserControl>

现在 <lvc:Cartesian Chart> 的绑定(来自 LiveCharts https://lvcharts.net/App/examples/v1/wpf/Basic%20Line%20Chart)正在运行,ChartParams 变量已完全评估,我可以访问系列集合。

但是,如果我查看更深的嵌套 <lvc:Axis>(通过 LiveVisualTree),则永远不会评估 Title 属性。

我错过了什么?为什么我不能从 <lvc:Axis> 中绑定到 ChartParams?

感谢任何帮助,如有必要,将 post 进一步编码。

编辑: 我应该补充一点,当应用程序是 运行 并且我在 Xaml 中触摸我的 Axis.Title 时,它会重新评估然后显示结果作为预期

问题是,Axis 元素没有在绑定解析时添加到可视化树中。作为图表基础 Canvas 子项的所有可见元素稍后添加(在引发图表控件的 FrameworkElement.Loaded 事件后很长时间)。因此,绑定的数据绑定例如AxisSeparator 等使用 RelativeSource 到他们的视觉父级将指向任何地方(除非你在相关目标元素添加到 Canvas 之后设置绑定(需要 C#而不是 XAML) 通过观察 CartesianChart.Content.LayoutUpdated 事件,但我建议不要这样做)。

推荐的解决方案是改为绑定到 DataContext

您可以将 UserControl 本身设置为它自己的 DataContext:

PeakrowChartGroupControl.xaml.cs

partial class PeakrowChartGroupControl : UserControl
{
  public PeakrowChartGroupControl()
  {
    InitializeComponent();
    this.DataContext = this;
  }
}

PeakrowChartGroupControl.xaml

<UserControl x:Class="DryLab.Peakmovement.RetentionChartControl">
    <Grid>
        <lvc:CartesianChart x:Name="cc" Series="{Binding ChartParams.Seriescollection}">
            <lvc:CartesianChart.AxisY>
                <lvc:Axis Title="{Binding ChartParams.TitleAxY}" 
                          LabelFormatter="{Binding ChartParams.Formatter}" />
            </lvc:CartesianChart.AxisY>
            <lvc:CartesianChart.AxisX>
                <lvc:Axis Title="{Binding ChartParams.TitleAxX}" 
                          Labels="{Binding ChartParams.Labels}" />
            </lvc:CartesianChart.AxisX>
        </lvc:CartesianChart>
    </Grid>
</UserControl>

或者,例如,如果 UserControl.DataContext 已经设置为其他内容,您可以将图表 DataContext 明确设置为例如 ChartParams 属性 RetentionChartControl:

PeakrowChartGroupControl.xaml

<UserControl x:Class="DryLab.Peakmovement.RetentionChartControl">
    <Grid>
        <lvc:CartesianChart DataContext="{Binding ChartParams, RelativeSource={RelativeSource AncestorType=local:RetentionChartControl}}" 
                            Series="{Binding Seriescollection}">
            <lvc:CartesianChart.AxisY>
                <lvc:Axis Title="{Binding TitleAxY}" 
                          LabelFormatter="{Binding Formatter}" />
            </lvc:CartesianChart.AxisY>
            <lvc:CartesianChart.AxisX>
                <lvc:Axis Title="{Binding TitleAxX}" 
                          Labels="{Binding Labels}" />
            </lvc:CartesianChart.AxisX>
        </lvc:CartesianChart>
    </Grid>
</UserControl>