WPF:渲染时绑定和实际值之间的差异
我正在从事一个相当大的项目,这就是为什么我不能真正粘贴工作代码的原因,但也许你可以从阅读症状中给我一个提示,说明什么是错误的。否则,我必须看看如何在一个较小的项目中重新创建问题,并将其粘贴到这里 我有一个自定义控件,它继承自WPF:渲染时绑定和实际值之间的差异,wpf,Wpf,我正在从事一个相当大的项目,这就是为什么我不能真正粘贴工作代码的原因,但也许你可以从阅读症状中给我一个提示,说明什么是错误的。否则,我必须看看如何在一个较小的项目中重新创建问题,并将其粘贴到这里 我有一个自定义控件,它继承自TreeView,我们称之为MyTreeView。此控件正在使用它自己的容器,我们将其称为mytreevieItems 整件事都经过了设计和调整,看起来像一个家谱或组织结构图(水平而不是垂直,父母在上面,孩子在下面)。连接线在MyTreeView的OnRender过程中绘制
TreeView
,我们称之为MyTreeView
。此控件正在使用它自己的容器,我们将其称为mytreevieItem
s
整件事都经过了设计和调整,看起来像一个家谱或组织结构图(水平而不是垂直,父母在上面,孩子在下面)。连接线在MyTreeView
的OnRender
过程中绘制
Protected Overrides Sub OnRender(drawingContext As DrawingContext)
Dim bounds As ItemBounds = Nothing
If (Me.ConnectorPen IsNot Nothing) Then
Me.GetItemBounds(Me, bounds)
Me.DrawConnections(Me.ConnectorPen, drawingContext, bounds)
End If
MyBase.OnRender(drawingContext)
End Sub
ConnectorPen
是一个类型为Pen
的依赖属性,ItemBounds
是一个小的层次化辅助类,包含所有mytreeItem
内容的边界矩形
GetItemBounds
收集每个MyTreeViewItem
内容的边界矩形
Private Sub GetItemBounds(parent As ItemsControl, ByRef bounds As ItemBounds)
Dim tvi As MyTreeViewItem
Dim topLeft As Point
Dim bottomRight As Point
Dim current As ItemBounds = Nothing
For Each item As Object In parent.Items
tvi = TryCast(parent.ItemContainerGenerator.ContainerFromItem(item), MyTreeViewItem)
If (tvi IsNot Nothing) Then
topLeft = tvi.Content.TranslatePoint(New Point(0, 0), Me)
bottomRight = tvi.Content.TranslatePoint(New Point(tvi.Content.ActualWidth, tvi.Content.ActualHeight), Me)
If (bounds Is Nothing) Then
bounds = New ItemBounds
bounds.Bounds = New Rect(topLeft, bottomRight)
current = bounds
Else
current = New ItemBounds
current.Bounds = New Rect(topLeft, bottomRight)
bounds.Children.Add(current)
End If
End If
Me.GetItemBounds(tvi, current)
Next item
End Sub
<Style TargetType="{x:Type local:MyTreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
IsItemsHost="True"
Margin="0,20,0,0" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
...
</Style>
tvi.Content
是保存当前项目内容的ContentPresenter
DrawConnections
根据收集的项目边界绘制连接线:
Private Sub DrawConnections(p As Pen, drawingContext As DrawingContext, bounds As ItemBounds)
Dim minChildTop As Double
Dim middle As Double
If (bounds Is Nothing) OrElse (bounds.Children Is Nothing) OrElse (bounds.Children.Count = 0) Then
Exit Sub
End If
If (bounds.Children.Count > 1) Then
minChildTop = bounds.Children.Min(Of Double)(Function(x As ItemBounds) x.Bounds.Top)
middle = bounds.Bounds.Bottom + ((minChildTop - bounds.Bounds.Bottom) / 2)
drawingContext.DrawLine(p, bounds.Bounds.BottomCenter,
New Point(bounds.Bounds.BottomCenter.X, middle))
drawingContext.DrawLine(p, New Point(bounds.Children.First.Bounds.TopCenter.X, middle),
New Point(bounds.Children.Last.Bounds.TopCenter.X, middle))
End If
For Each item As ItemBounds In bounds.Children
If (bounds.Children.Count > 1) Then
drawingContext.DrawLine(p, New Point(item.Bounds.TopCenter.X, middle),
item.Bounds.TopCenter)
Else
drawingContext.DrawLine(p, bounds.Bounds.BottomCenter,
item.Bounds.TopCenter)
End If
Me.DrawConnections(p, drawingContext, item)
Next item
End Sub
BottomCenter
和TopCenter
是Rect
的扩展方法,用于确定将上边缘或下边缘切成两个相同长度的两半的点
到目前为止一切正常。父项与其子项之间的空间由添加到StackPanel
的固定边距创建,该边距用作默认样式mytreeItem
中的ItemsPanel
Private Sub GetItemBounds(parent As ItemsControl, ByRef bounds As ItemBounds)
Dim tvi As MyTreeViewItem
Dim topLeft As Point
Dim bottomRight As Point
Dim current As ItemBounds = Nothing
For Each item As Object In parent.Items
tvi = TryCast(parent.ItemContainerGenerator.ContainerFromItem(item), MyTreeViewItem)
If (tvi IsNot Nothing) Then
topLeft = tvi.Content.TranslatePoint(New Point(0, 0), Me)
bottomRight = tvi.Content.TranslatePoint(New Point(tvi.Content.ActualWidth, tvi.Content.ActualHeight), Me)
If (bounds Is Nothing) Then
bounds = New ItemBounds
bounds.Bounds = New Rect(topLeft, bottomRight)
current = bounds
Else
current = New ItemBounds
current.Bounds = New Rect(topLeft, bottomRight)
bounds.Children.Add(current)
End If
End If
Me.GetItemBounds(tvi, current)
Next item
End Sub
<Style TargetType="{x:Type local:MyTreeViewItem}" BasedOn="{StaticResource {x:Type TreeViewItem}}">
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal"
HorizontalAlignment="Center"
IsItemsHost="True"
Margin="0,20,0,0" />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
...
</Style>
现在,子项使用ItemSpacing
提供的空间(这样可以工作),但连接线的绘制失败。看起来所有mytreevieItem
s内容的边界矩形的收集在应用此边界之前完成
我已经尝试过使用itemspacking
依赖项属性的AffectsRender
和affectsrange
设置,但没有任何帮助
您能告诉我,为什么使用固定页边距,以及当页边距来自绑定时为什么不起作用吗?能否显示OnRender
?我已根据描述复制了您的代码,但问题不存在。请在描述中添加更多代码。