這個問題的標題可能是錯誤的,我不知道該如何措辭。我正試圖實作一個非常簡單的儀表板,用戶可以在Canvas控制元件中拖動控制元件。我寫了一個MoveThumb類,它繼承了Thumb來實作這一目的。它作業得足夠好。現在,我想確保用戶不能在Canvas之外移動可拖動的控制元件。在這個 MoveThumb 類中寫出限制拖動邊界的邏輯本身是很簡單的:
Public Class MoveThumb
Inherits Thumb
Public Sub New()
AddHandler DragDelta, New DragDeltaEventHandler(AddressOf Me.MoveThumb_DragDelta)
結束 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 然后
If right e.HorizontalChange < canvasWidth Then
If bottom e.VerticalChange > canvasHeight Then
Canvas.SetLeft(item, left e.HorizontalChange)
Canvas.SetTop(item, top e.VerticalChange)
結束 If
End If
結束 若
結束 若
結束 若
End Sub
結束 類別
而XML:
<Window x:Class="MainWindow"/span>
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"。
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"/span>
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"/span>
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"/span>
xmlns:local="clr-namespace:diagramDesigner"/span>
xmlns:s="clr-namespace:diagramDesigner"。
mc:Ignorable="d"。
Title="主視窗" 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}}"/span>>
<s:MoveThumb Template="{StaticResource MoveThumbTemplate}" Cursor="SizeAll"/>
<ContentPresenter Content="{TemplateBinding ContentControl.Content}" />
</Grid>
</ControlTemplate>
</Canvas.Resources>
<ContentControl Name="DesignerItem"/span>
寬度="100"。
高度="100"。
Canvas.Top="100"/span>
Canvas.Left="100" 帆布。
Template="{StaticResource DesignerItemTemplate}">
<Ellipse Fill="Blue"/span> IsHitTestVisible="False"/span>/>
</ContentControl>
</Canvas>
</Grid>
</Window>
問題是,我在該MoveThumb類中明確說明了畫布的寬度和高度,這意味著如果我的視窗改變了大小,而畫布也改變了大小,那么拖動的邊界將保持不變。理想情況下,我希望將 canvasWidth 和 canvasHeight 與 Canvas 的 actualWidth 和 actualHeight 系結。
我不確定什么是實作它的最佳方式。在MoveThumb_DragDelta函式中獲取actualWidth和actualHeight的值,例如actualWidth = mainWindow.Canvas1.ActualWidth將是快速和簡單的,但是非常糟糕的編碼實踐。
事實上,我想最好是將限制作為引數傳遞給MoveThumb的建構式,并作為全域欄位/屬性存盤,但我沒有看到一個方法,因為這個類在XML代碼中被用作模板,而不是從代碼后臺生成。我不確定這是否可行,因為 MoveThumb 可能只被實體化一次(在創建控制元件期間),所以當 Canvas 之后改變其大小時,它將不起作用。
因此,我可能應該在 Canvas1 的 actualWidth 和 MoveThumb 的 canvasWidth(作為全域屬性宣告)之間進行某種單向系結。但是,我又不知道如何訪問它,因為MoveThumb是作為ControlTemplate的TargetType在Canvas.Resources里面使用的。
我對WPF還很陌生,感覺應該有一些非常簡單的方法來實作這一點,但我沒有看到。誰能幫幫我?
uj5u.com熱心網友回復:
使用依賴屬性的例子:
public partial class MoveThumb : Thumbprivate double privateCanvasWidth = double.NaN, privateCanvasHeight = double.NaN。
private static readonly Binding bindingActualWidth = new Binding()
{
Path = new PropertyPath(ActualWidthProperty)。
RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Canvas), 1)
};
private static readonly Binding bindingActualHeight = new Binding()
{
Path = new PropertyPath(ActualHeightProperty)。
RelativeSource = new RelativeSource(RelativeSourceMode.FindAncestor, typeof(Canvas), 1)
};
public MoveThumb()
{
DragDelta = MoveThumb_DragDelta;
SetBinding(CanvasWidthProperty, bindingActualWidth)。
SetBinding(CanvasHeightProperty, bindingActualHeight)。
}
static MoveThumb()?
{
DefaultStyleKeyProperty.OverrideMetadata(typeof(MoveThumb), new FrameworkPropertyMetadata(typeof(MoveThumb)))。
}
private static void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e)。
{
MoveThumb thumb = (MoveThumb)sender;
/FrameworkElement item = thumb.MovableContent;
//if (item == null)/span>
//{
//return;
//}
double left = Canvas.GetLeft(thumb);
double top = Canvas.GetTop(thumb);
double right = left thumb.ActualWidth;
double bottom = top thumb.ActualHeight;
double canvasWidth = thumb.privateCanvasWidth;
if (double.IsNaN(canvasWidth))
canvasWidth = 450;
double canvasHeight = thumb.privateCanvasHeight;
if (double.IsNaN(canvasHeight))
canvasWidth = 800;
left = e.HorizontalChange;
top = e.VerticalChange;
right = e.HorizontalChange;
bottom = e.VerticalChange。
if (left > 0 & &
top > 0 &&
右邊 < canvasWidth &&
底部 < canvasHeight)
{
Canvas.SetLeft(thumb, left);
Canvas.SetTop(thumb, top);
}
}
}
// DependecyProperties
[ContentProperty(nameof(MovableContent))]
public partial class MoveThumb
{
// <summary>Canvas Width.</summary>
public double CanvasWidth
{
get => (double)GetValue(CanvasWidthProperty)。
set => SetValue(CanvasWidthProperty, value)。
}
// <summary>/span>< 見cref="DependencyProperty"/>的屬性<見cref="CanvasWidth"/>。 </summary>。
public static readonly DependencyProperty CanvasWidthProperty =
DependencyProperty. Register(nameof(CanvasWidth), typeof(double) 。typeof(MoveThumb), new PropertyMetadata(double. NaN, CanvasSizeChanged))。)
// <summary>Canvas Height.</summary>
public double CanvasHeight
{
get => (double)GetValue(CanvasHeightProperty)。
set => SetValue(CanvasHeightProperty, value)。
}
// <summary>/span>< 見cref="DependencyProperty"/>的屬性<見cref="CanvasHeight"/>。 </summary>。
public static readonly DependencyProperty CanvasHeightProperty =
DependencyProperty. Register(nameof(CanvasHeight), typeof(double), typeof(MoveThumb), new PropertyMetadata(double. NaN, CanvasSizeChanged))。)
//Property change handler.
//該代碼顯示為一個例子。
private static void CanvasSizeChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)。
{
MoveThumb thumb = (MoveThumb)d;
if (e.Property == CanvasWidthProperty)
{
thumb.privateCanvasWidth = (double)e.NewValue。
}
else if (e.Property == CanvasHeightProperty)
{
thumb.privateCanvasHeight = (double)e.NewValue。
}
else
{
throw new Exception("God knows what happened!") 。
}
MoveThumb_DragDelta(thumb, new DragDeltaEventArgs(0, 0) )。)
}
// <summary>可移動的內容。</summary>
public FrameworkElement MovableContent
{
get => (FrameworkElement)GetValue(MovableContentProperty);
set => SetValue(MovableContentProperty, value) 。
}
// <summary>/span>< 見cref="DependencyProperty"/>的屬性<見cref="MovableContent"/>/span>。 </summary>。
public static readonly DependencyProperty MovableContentProperty =
DependencyProperty. 注冊(nameof(MovableContent), typeof(FrameworkElement), typeof(MoveThumb), new PropertyMetadata(null))。
在專案中添加主題 "ThemesGeneric.xaml":
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"/span>
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"。
xmlns:customcontrols="clr-namespace:EmbedContent.CustomControls"
xmlns:s="clr-namespace:Febr20y">/span>
<Style TargetType="{x:Type s:MoveThumb}">/span>
<Setter Property="Template">
<Setter.Value>/span>
<ControlTemplate TargetType="{x:Type s:MoveThumb}"/span>>
<ContentPresenter Content="{TemplateBinding MovableContent}"/span>/>
</ControlTemplate>
</Setter.Value>/span>
</Setter>/span>
</Style>>
</ResourceDictionary>/span>
<Grid>
<Canvas x:Name="Canvas1">
<s:MoveThumb x:Name="DesignerItem"
Width="100"/span>
高度="100"
Canvas.Top="100"/span>
Canvas.Left="100">>
<Ellipse Fill="Blue"/span>/>
</s:MoveThumb>/span>
</Canvas>/span>
</Grid>/span>
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/315759.html
標籤:
