ist hier, den ich vor einer Weile gemacht, es erlaubt Move
und Resize
, aber Sie können die Move
Logik entfernen und es sollte funktionieren (der Stil noch ein bisschen chaotisch, aber es funktioniert ziemlich gut)
seine basierend auf ContentControl
so können Sie jede Element
innen addieren und Bewegen/Größe auf einem Canvas
, verwendet es 3 Adorners
, eine für Resize, eine für Verschieben und eine Information (aktuelle Größe)
Hier ist ein voll funktionierendes Beispiel anzuzeigen wenn Sie testen/verwenden/ändern/verbessern wollen :)
Code:
namespace WpfApplication21
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
}
public class ResizeThumb : Thumb
{
public ResizeThumb()
{
DragDelta += new DragDeltaEventHandler(this.ResizeThumb_DragDelta);
}
private void ResizeThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
Control designerItem = this.DataContext as Control;
if (designerItem != null)
{
double deltaVertical, deltaHorizontal;
switch (VerticalAlignment)
{
case VerticalAlignment.Bottom:
deltaVertical = Math.Min(-e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight);
designerItem.Height -= deltaVertical;
break;
case VerticalAlignment.Top:
deltaVertical = Math.Min(e.VerticalChange, designerItem.ActualHeight - designerItem.MinHeight);
Canvas.SetTop(designerItem, Canvas.GetTop(designerItem) + deltaVertical);
designerItem.Height -= deltaVertical;
break;
default:
break;
}
switch (HorizontalAlignment)
{
case HorizontalAlignment.Left:
deltaHorizontal = Math.Min(e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth);
Canvas.SetLeft(designerItem, Canvas.GetLeft(designerItem) + deltaHorizontal);
designerItem.Width -= deltaHorizontal;
break;
case HorizontalAlignment.Right:
deltaHorizontal = Math.Min(-e.HorizontalChange, designerItem.ActualWidth - designerItem.MinWidth);
designerItem.Width -= deltaHorizontal;
break;
default:
break;
}
}
e.Handled = true;
}
}
public class MoveThumb : Thumb
{
public MoveThumb()
{
DragDelta += new DragDeltaEventHandler(this.MoveThumb_DragDelta);
}
private void MoveThumb_DragDelta(object sender, DragDeltaEventArgs e)
{
Control designerItem = this.DataContext as Control;
if (designerItem != null)
{
double left = Canvas.GetLeft(designerItem);
double top = Canvas.GetTop(designerItem);
Canvas.SetLeft(designerItem, left + e.HorizontalChange);
Canvas.SetTop(designerItem, top + e.VerticalChange);
}
}
}
public class SizeAdorner : Adorner
{
private Control chrome;
private VisualCollection visuals;
private ContentControl designerItem;
protected override int VisualChildrenCount
{
get
{
return this.visuals.Count;
}
}
public SizeAdorner(ContentControl designerItem)
: base(designerItem)
{
this.SnapsToDevicePixels = true;
this.designerItem = designerItem;
this.chrome = new Control();
this.chrome.DataContext = designerItem;
this.visuals = new VisualCollection(this);
this.visuals.Add(this.chrome);
}
protected override Visual GetVisualChild(int index)
{
return this.visuals[index];
}
protected override Size ArrangeOverride(Size arrangeBounds)
{
this.chrome.Arrange(new Rect(new Point(0.0, 0.0), arrangeBounds));
return arrangeBounds;
}
}
}
XAML:
<Window x:Class="WpfApplication21.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication21"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<Style TargetType="{x:Type ContentControl}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type ContentControl}">
<Grid DataContext="{Binding RelativeSource={RelativeSource TemplatedParent}}">
<local:MoveThumb Cursor="SizeAll">
<local:MoveThumb.Style>
<Style TargetType="{x:Type local:MoveThumb}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:MoveThumb}">
<Rectangle Fill="Transparent" />
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</local:MoveThumb.Style>
</local:MoveThumb>
<Control x:Name="resizer">
<Control.Style>
<Style TargetType="{x:Type Control}">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type Control}">
<Grid>
<Grid Opacity="0" Margin="-3">
<local:ResizeThumb Height="3" Cursor="SizeNS" VerticalAlignment="Top" HorizontalAlignment="Stretch"/>
<local:ResizeThumb Width="3" Cursor="SizeWE" VerticalAlignment="Stretch" HorizontalAlignment="Left"/>
<local:ResizeThumb Width="3" Cursor="SizeWE" VerticalAlignment="Stretch" HorizontalAlignment="Right"/>
<local:ResizeThumb Height="3" Cursor="SizeNS" VerticalAlignment="Bottom" HorizontalAlignment="Stretch"/>
<local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNWSE" VerticalAlignment="Top" HorizontalAlignment="Left"/>
<local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNESW" VerticalAlignment="Top" HorizontalAlignment="Right"/>
<local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNESW" VerticalAlignment="Bottom" HorizontalAlignment="Left"/>
<local:ResizeThumb Width="7" Height="7" Margin="-2" Cursor="SizeNWSE" VerticalAlignment="Bottom" HorizontalAlignment="Right"/>
</Grid>
<Grid IsHitTestVisible="False" Opacity="1" Margin="-3">
<Grid.Resources>
<Style TargetType="{x:Type Ellipse}">
<Setter Property="SnapsToDevicePixels" Value="true" />
<Setter Property="Stroke" Value="#FFC8C8C8" />
<Setter Property="StrokeThickness" Value=".5" />
<Setter Property="Width" Value="7" />
<Setter Property="Height" Value="7" />
<Setter Property="Margin" Value="-2" />
<Setter Property="Fill" Value="Silver" />
</Style>
</Grid.Resources>
<Rectangle SnapsToDevicePixels="True" StrokeThickness="1" Margin="1" Stroke="Black" StrokeDashArray="4 4"/>
<Ellipse HorizontalAlignment="Left" VerticalAlignment="Top"/>
<Ellipse HorizontalAlignment="Right" VerticalAlignment="Top"/>
<Ellipse HorizontalAlignment="Left" VerticalAlignment="Bottom"/>
<Ellipse HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
</Grid>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Control.Style>
</Control>
<Grid x:Name="sizeInfo" SnapsToDevicePixels="True">
<Path Stroke="Red" StrokeThickness="1" Height="10" VerticalAlignment="Bottom" Margin="-2,0,-2,-15" Stretch="Fill" Data="M0,0 0,10 M 0,5 100,5 M 100,0 100,10"/>
<TextBlock Text="{Binding Width}" Background="White" Padding="3,0,3,0" Foreground="Red" Margin="0,0,0,-18" HorizontalAlignment="Center" VerticalAlignment="Bottom"/>
<Path Stroke="Red" StrokeThickness="1" Width="10" HorizontalAlignment="Right" Margin="0,-2,-15,-2" Stretch="Fill" Data="M5,0 5,100 M 0,0 10,0 M 0,100 10,100"/>
<TextBlock Text="{Binding Height}" Background="White" Foreground="Red" Padding="3,0,3,0" Margin="0,0,-18,0" HorizontalAlignment="Right" VerticalAlignment="Center">
<TextBlock.LayoutTransform>
<RotateTransform Angle="90" CenterX="1" CenterY="0.5"/>
</TextBlock.LayoutTransform>
</TextBlock>
</Grid>
<ContentPresenter Content="{TemplateBinding Content}"/>
</Grid>
<ControlTemplate.Triggers>
<Trigger Property="IsMouseOver" Value="True">
<Setter TargetName="sizeInfo" Property="Visibility" Value="Visible" />
</Trigger>
<Trigger Property="IsMouseOver" Value="False">
<Setter TargetName="sizeInfo" Property="Visibility" Value="Hidden" />
</Trigger>
</ControlTemplate.Triggers>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</Window.Resources>
<Canvas>
<ContentControl Width="183" Height="110" Canvas.Left="166" Canvas.Top="50" />
</Canvas>
</Window>
Ergebnis:


Mit Inhalt innen (Button)

Leider die Cursor nicht zeigen, wenn SnipTool mit
ich diese Probe in der Vergangenheit verwendet haben, aber Sie müssen die Kontrolle klicken. Vielleicht können Sie es anpassen, um Maus-Hover-Ereignisse zu abonnieren (Hittest oder etwas) http://denisvuyka.wordpress.com/2007/10/15/wpf-simple-adorner-usage-with-drag-and-resize-operations/ –