不调用 ConvertBack
ConvertBack is not called
我正在尝试编写一个通用控件,我可以在其中使用转换器传递不同的数据模型(全部实现 INotifyPropertyChanged
)。数据在控件中毫无问题地传递并正确显示(其中一些还使用 IMultivalueConverts
,可以完美地工作)。虽然修改了数据,但是没有调用MainControl的IMultiValueConverter
通用控件应该只显示根据 ObservableCollection 中的坐标计算的矩形。
我将 DebugConverters 放在所有绑定上,除了顶部的 ConvertBack 之外,所有内容似乎都已更新。来自 ListBox 的 SourceUpdate 也被调用。
我用不同的 NotifyOn...Updated、Mode 和 UpdateSourceTrigger 尝试了这个转换器,我总是看到控件中的值发生变化,但从未看到主控件的 ConvertBack。
使用的部分数据模板(更新正确完成),所有 DegreeTo... 转换器都是双向调用的
<DataTemplate x:Key="RectangleWithLabel">
<Canvas IsHitTestVisible="True">
<Rectangle x:Name="RectangleROI" MouseLeftButtonDown="myCanvas_PreviewMouseLeftButtonDown" >
<!--
<Rectangle.Visibility>
<Binding Path="ROI" Converter="{StaticResource NullToVisibilityConverter}"/>
</Rectangle.Visibility>
-->
<Canvas.Left>
<MultiBinding Converter="{StaticResource DegreeToScreenPixelConverterH}" Mode="TwoWay" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged" >
<Binding Path="ROI.Begin.PosH" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" />
<Binding Path="DataContext.UsedCoordinateSystem" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}" NotifyOnSourceUpdated="True" Mode="TwoWay" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged" />
</MultiBinding>
</Canvas.Left>
<Canvas.Top>
<MultiBinding Converter="{StaticResource DegreeToScreenPixelConverterV}" Mode="TwoWay" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged">
<Binding Path="ROI.Begin.PosV" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" />
<Binding Path="DataContext.UsedCoordinateSystem" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}" NotifyOnSourceUpdated="True" Mode="TwoWay" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</Canvas.Top>
<Rectangle.Width>
<MultiBinding Converter="{StaticResource DegreeToScreenPixelWidthConverter}" Mode="TwoWay" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged">
<Binding Path="ROI.Begin.PosH" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" />
<Binding Path="ROI.End.PosH" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" />
<Binding Path="DataContext.UsedCoordinateSystem" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}" NotifyOnSourceUpdated="True" Mode="TwoWay" NotifyOnTargetUpdated="True"/>
</MultiBinding>
</Rectangle.Width>
<Rectangle.Height>
<MultiBinding Converter="{StaticResource DegreeToScreenPixelHeightConverter}" Mode="TwoWay" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged">
<Binding Path="ROI.Begin.PosV" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True"/>
<Binding Path="ROI.End.PosV" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" />
<Binding Path="DataContext.UsedCoordinateSystem" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}" NotifyOnSourceUpdated="True" Mode="TwoWay" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</Rectangle.Height>
<Rectangle.Fill>#33FF0000</Rectangle.Fill>
<Rectangle.Stroke>#FF00FF00</Rectangle.Stroke>
<Rectangle.IsHitTestVisible>true</Rectangle.IsHitTestVisible>
</Rectangle>
包含所有数据的列表视图:
<ListView ItemsSource="{Binding Rectangles, Mode=TwoWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" x:Name="listBox" Width="{Binding ActualWidth, ElementName=ImageControl, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" Height="{Binding ActualHeight, ElementName=ImageControl, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}" ItemTemplate="{StaticResource RectangleWithLabel}" MouseMove="ListBox_MouseMove" DataContextChanged="ListBox_DataContextChanged" SourceUpdated="ListBox_SourceUpdated" IsSynchronizedWithCurrentItem="True" TargetUpdated="ListBox_TargetUpdated" />
从父级调用 ImageViewer,这里在到达 ImageViewer 的途中调用转换器,但从未调用 ConvertBack:
<common:ImageViewer x:Name="ctrlImage" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<common:ImageViewer.DataContext>
<MultiBinding Converter="{StaticResource ConverterWhichIsOnlyCalledOneWay}" Mode="TwoWay" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged">
<Binding Path="." UpdateSourceTrigger="PropertyChanged" Mode="TwoWay" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True"/>
</MultiBinding>
</common:ImageViewer.DataContext>
</common:ImageViewer>
如何调用 ConvertBack
?
编辑:
我概述了控件和转换器。我想我错了,应该调用 ConvertBack,一切都在更新,即使没有大转换器。但是我在向 ObservableCollection
添加一些元素时仍然卡住了。当我添加一些值时,这些值出现在 MainWindow 的 DataContext 中。但是转换器没有被触发。当我将 Observable.Count
作为绑定添加到 Big Converter 时,更新被触发,但所有绑定都丢失了。
对原始代码的更改是:将所有内部变量更改为 DependencyProperties
,这使得 ObservableCollection
.
中的单个条目的更新变得可靠
Overview of the GUI and the used converters
是时候自己回答问题了:
当两个元件之间存在直接连接时,假设变化通过转换器向下传播时我错了。
因此,如果我在深度嵌套中有一个元素(只需将其视为树的叶子),并且它曾经通过转换器显示一次(这会改变 一些 其他对象)并且在没有转换器的情况下同时更新元素而不调用转换器。 WPF 非常聪明,可以看到值是相同的,并且不会通过转换器向上和向下传递变化。
我正在尝试编写一个通用控件,我可以在其中使用转换器传递不同的数据模型(全部实现 INotifyPropertyChanged
)。数据在控件中毫无问题地传递并正确显示(其中一些还使用 IMultivalueConverts
,可以完美地工作)。虽然修改了数据,但是没有调用MainControl的IMultiValueConverter
通用控件应该只显示根据 ObservableCollection 中的坐标计算的矩形。
我将 DebugConverters 放在所有绑定上,除了顶部的 ConvertBack 之外,所有内容似乎都已更新。来自 ListBox 的 SourceUpdate 也被调用。
我用不同的 NotifyOn...Updated、Mode 和 UpdateSourceTrigger 尝试了这个转换器,我总是看到控件中的值发生变化,但从未看到主控件的 ConvertBack。
使用的部分数据模板(更新正确完成),所有 DegreeTo... 转换器都是双向调用的
<DataTemplate x:Key="RectangleWithLabel">
<Canvas IsHitTestVisible="True">
<Rectangle x:Name="RectangleROI" MouseLeftButtonDown="myCanvas_PreviewMouseLeftButtonDown" >
<!--
<Rectangle.Visibility>
<Binding Path="ROI" Converter="{StaticResource NullToVisibilityConverter}"/>
</Rectangle.Visibility>
-->
<Canvas.Left>
<MultiBinding Converter="{StaticResource DegreeToScreenPixelConverterH}" Mode="TwoWay" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged" >
<Binding Path="ROI.Begin.PosH" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" />
<Binding Path="DataContext.UsedCoordinateSystem" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}" NotifyOnSourceUpdated="True" Mode="TwoWay" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged" />
</MultiBinding>
</Canvas.Left>
<Canvas.Top>
<MultiBinding Converter="{StaticResource DegreeToScreenPixelConverterV}" Mode="TwoWay" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged">
<Binding Path="ROI.Begin.PosV" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" />
<Binding Path="DataContext.UsedCoordinateSystem" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}" NotifyOnSourceUpdated="True" Mode="TwoWay" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</Canvas.Top>
<Rectangle.Width>
<MultiBinding Converter="{StaticResource DegreeToScreenPixelWidthConverter}" Mode="TwoWay" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged">
<Binding Path="ROI.Begin.PosH" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" />
<Binding Path="ROI.End.PosH" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" />
<Binding Path="DataContext.UsedCoordinateSystem" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}" NotifyOnSourceUpdated="True" Mode="TwoWay" NotifyOnTargetUpdated="True"/>
</MultiBinding>
</Rectangle.Width>
<Rectangle.Height>
<MultiBinding Converter="{StaticResource DegreeToScreenPixelHeightConverter}" Mode="TwoWay" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged">
<Binding Path="ROI.Begin.PosV" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True"/>
<Binding Path="ROI.End.PosV" Mode="TwoWay" UpdateSourceTrigger="PropertyChanged" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" />
<Binding Path="DataContext.UsedCoordinateSystem" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type UserControl}}" NotifyOnSourceUpdated="True" Mode="TwoWay" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged"/>
</MultiBinding>
</Rectangle.Height>
<Rectangle.Fill>#33FF0000</Rectangle.Fill>
<Rectangle.Stroke>#FF00FF00</Rectangle.Stroke>
<Rectangle.IsHitTestVisible>true</Rectangle.IsHitTestVisible>
</Rectangle>
包含所有数据的列表视图:
<ListView ItemsSource="{Binding Rectangles, Mode=TwoWay, NotifyOnTargetUpdated=True, NotifyOnSourceUpdated=True, NotifyOnValidationError=True, UpdateSourceTrigger=PropertyChanged, ValidatesOnDataErrors=True, ValidatesOnExceptions=True}" x:Name="listBox" Width="{Binding ActualWidth, ElementName=ImageControl, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" Height="{Binding ActualHeight, ElementName=ImageControl, Mode=OneWay,UpdateSourceTrigger=PropertyChanged}" Background="{x:Null}" BorderBrush="{x:Null}" Foreground="{x:Null}" ItemTemplate="{StaticResource RectangleWithLabel}" MouseMove="ListBox_MouseMove" DataContextChanged="ListBox_DataContextChanged" SourceUpdated="ListBox_SourceUpdated" IsSynchronizedWithCurrentItem="True" TargetUpdated="ListBox_TargetUpdated" />
从父级调用 ImageViewer,这里在到达 ImageViewer 的途中调用转换器,但从未调用 ConvertBack:
<common:ImageViewer x:Name="ctrlImage" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" >
<common:ImageViewer.DataContext>
<MultiBinding Converter="{StaticResource ConverterWhichIsOnlyCalledOneWay}" Mode="TwoWay" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True" UpdateSourceTrigger="PropertyChanged">
<Binding Path="." UpdateSourceTrigger="PropertyChanged" Mode="TwoWay" NotifyOnSourceUpdated="True" NotifyOnTargetUpdated="True"/>
</MultiBinding>
</common:ImageViewer.DataContext>
</common:ImageViewer>
如何调用 ConvertBack
?
编辑:
我概述了控件和转换器。我想我错了,应该调用 ConvertBack,一切都在更新,即使没有大转换器。但是我在向 ObservableCollection
添加一些元素时仍然卡住了。当我添加一些值时,这些值出现在 MainWindow 的 DataContext 中。但是转换器没有被触发。当我将 Observable.Count
作为绑定添加到 Big Converter 时,更新被触发,但所有绑定都丢失了。
对原始代码的更改是:将所有内部变量更改为 DependencyProperties
,这使得 ObservableCollection
.
Overview of the GUI and the used converters
是时候自己回答问题了:
当两个元件之间存在直接连接时,假设变化通过转换器向下传播时我错了。
因此,如果我在深度嵌套中有一个元素(只需将其视为树的叶子),并且它曾经通过转换器显示一次(这会改变 一些 其他对象)并且在没有转换器的情况下同时更新元素而不调用转换器。 WPF 非常聪明,可以看到值是相同的,并且不会通过转换器向上和向下传递变化。