未评估嵌套 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
事件后很长时间)。因此,绑定的数据绑定例如Axis
或 Separator
等使用 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>
我有一个嵌套的 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
事件后很长时间)。因此,绑定的数据绑定例如Axis
或 Separator
等使用 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>