【发布时间】:2021-11-11 12:35:43
【问题描述】:
这个问题的标题可能是错误的,我不知道如何表达它。我正在尝试实现一个非常简单的仪表板,其中用户可以在Canvas 控件内拖动控件。我写了一个继承Thumb 的MoveThumb 类来实现这一点。它运行良好。现在,我想确保用户不能将可拖动控件移到Canvas 之外。编写逻辑本身来限制这个MoveThumb类内的拖动边界很简单:
Public Class MoveThumb
Inherits Thumb
Public Sub New()
AddHandler DragDelta, New DragDeltaEventHandler(AddressOf Me.MoveThumb_DragDelta)
End Sub
Private Sub MoveThumb_DragDelta(ByVal sender As Object, ByVal e As DragDeltaEventArgs)
Dim item As Control = TryCast(Me.DataContext, Control)
If item IsNot Nothing Then
Dim left As Double = Canvas.GetLeft(item)
Dim top As Double = Canvas.GetTop(item)
Dim right As Double = left + item.ActualWidth
Dim bottom As Double = top + item.ActualHeight
Dim canvasWidth = 450
Dim canvasHeight = 800
If left + e.HorizontalChange > 0 Then
If top + e.VerticalChange > 0 Then
If right + e.HorizontalChange < canvasWidth Then
If bottom + e.VerticalChange > canvasHeight Then
Canvas.SetLeft(item, left + e.HorizontalChange)
Canvas.SetTop(item, top + e.VerticalChange)
End If
End If
End If
End If
End If
End Sub
End Class
还有 XML:
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:diagramDesigner"
xmlns:s="clr-namespace:diagramDesigner"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Canvas x:Name="Canvas1">
<Canvas.Resources>
<ControlTemplate x:Key="MoveThumbTemplate" TargetType="{x:Type s:MoveThumb}">
<Rectangle Fill="Transparent"/>
</ControlTemplate>
<ControlTemplate x:Key="DesignerItemTemplate" TargetType="ContentControl">
<Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<s:MoveThumb Template="{StaticResource MoveThumbTemplate}" Cursor="SizeAll"/>
<ContentPresenter Content="{TemplateBinding ContentControl.Content}"/>
</Grid>
</ControlTemplate>
</Canvas.Resources>
<ContentControl Name="DesignerItem"
Width="100"
Height="100"
Canvas.Top="100"
Canvas.Left="100"
Template="{StaticResource DesignerItemTemplate}">
<Ellipse Fill="Blue" IsHitTestVisible="False"/>
</ContentControl>
</Canvas>
</Grid>
</Window>
问题是,我明确说明了 MoveThumb 类中画布的宽度和高度,这意味着如果我的窗口改变大小,并且画布改变大小,拖动边界将保持不变。理想情况下,我想将canvasWidth 和canvasHeight 绑定到画布的actualWidth 和actualHeight。
我不确定实现它的最佳方法是什么。使用actualWidth = mainWindow.Canvas1.ActualWidth 之类的方法获取MoveThumb_DragDelta 函数中的actualWidth 和actualHeight 值会既快速又简单,但编码习惯非常糟糕。
理想情况下,我想最好将限制作为参数传递给MoveThumb 的构造函数并存储为全局字段/属性,但我看不到这样做的方法,因为此类用作XML 代码中的模板,而不是从代码隐藏生成的。我不确定这是否会起作用,因为MoveThumb 可能只被实例化一次(在创建控件期间),所以当Canvas 之后改变它的大小时它不会起作用。
所以我可能应该在Canvas1 的actualWidth 和MoveThumb 的canvasWidth(声明为全局属性)之间进行某种单向绑定。但同样,我不知道如何访问它,因为MoveThumb 在Canvas.Resources 中用作TargetType 的ControlTemplate。
我对 WPF 还是很陌生,感觉应该有一些非常简单的方法来实现这一点,但我没有看到它。有人可以帮忙吗?
【问题讨论】:
-
您可以在 MoveThumb 中声明一个将接收大小的 DependecyProperty,然后在 XAML 中设置它所需的绑定。如果你懂 C#,我可以举个例子。
-
@EldHasp 我对 C# 的了解与 VB.NET 一样多。当然,一个例子会很好,因为我还没有了解 DependecyProperties。
标签: wpf vb.net templates binding resources