OK, I got the resize working. Here is the code for Draggable window with Resize capability:
1) Put the following code in DraggablePanel.cs to create a Draggable Panel. You can put any silverlight UIElement as content of this control to make it draggable. (No XAML file needed for this control).
public class DraggablePanel : Grid
{
Point beginP;
Point currentP;
bool dragOn = false;
string resize = "";
#region CanResize
/// <summary>
/// Identifies the CanResize dependency property.
/// </summary>
public static readonly DependencyProperty CanResizeProperty = DependencyProperty.Register("CanResize", typeof(bool), typeof(DraggablePanel), null);
/// <summary>
/// Gets or sets the CanResize possible Value of the bool object.
/// </summary>
public bool CanResize
{
get { return (bool)GetValue(CanResizeProperty); }
set { SetValue(CanResizeProperty, value); }
}
#endregion CanResize
public DraggablePanel() : base()
{
this.MouseLeftButtonDown += new MouseButtonEventHandler(DraggablePanel_MouseLeftButtonDown);
this.MouseLeftButtonUp += new MouseButtonEventHandler(DraggablePanel_MouseLeftButtonUp);
this.MouseMove += new MouseEventHandler(DraggablePanel_MouseMove);
this.CanResize = true;
}
void DraggablePanel_MouseMove(object sender, MouseEventArgs e)
{
currentP = e.GetPosition(null);
if (dragOn)
{
double x0 = System.Convert.ToDouble(this.GetValue(Canvas.LeftProperty));
double y0 = System.Convert.ToDouble(this.GetValue(Canvas.TopProperty));
if (resize == "")
{
this.SetValue(Canvas.LeftProperty, x0 + currentP.X - beginP.X);
this.SetValue(Canvas.TopProperty, y0 + currentP.Y - beginP.Y);
}
else
{
UIElement c = this.Children[0];
if (resize.IndexOf("n") > -1) //north
{
this.SetValue(Canvas.TopProperty, y0 + currentP.Y - beginP.Y);
this.Height = this.ActualHeight - (currentP.Y - beginP.Y);
}
if (resize.IndexOf("s") > -1) //south
{
this.Height = this.ActualHeight + (currentP.Y - beginP.Y);
}
if (resize.IndexOf("w") > -1) //w
{
this.SetValue(Canvas.LeftProperty, x0 + currentP.X - beginP.X);
this.Width = this.ActualWidth - (currentP.X - beginP.X);
}
if (resize.IndexOf("e") > -1) //south
{
this.Width = this.ActualWidth + (currentP.X - beginP.X);
}
}
beginP = currentP;
}
if (this.CanResize)
{
double x0 = currentP.X;
double y0 = currentP.Y;
Point P = GetElementPosition(this);
double x1 = P.X;
double y1 = P.Y;
double x2 = x1 + this.ActualWidth;
double y2 = y1 + this.ActualHeight;
if (Math.Abs(x0 - x1) < 6 && Math.Abs(y0 - y1) < 6)
resize = "nw";
else if (Math.Abs(x0 - x1) < 6 && Math.Abs(y2 - y0) < 6)
resize = "sw";
else if (Math.Abs(x2 - x0) < 6 && Math.Abs(y2 - y0) < 6)
resize = "se";
else if (Math.Abs(x2 - x0) < 6 && Math.Abs(y0 - y1) < 6)
resize = "ne";
if (Math.Abs(y0 - y1) < 4)
resize = "n";
else if (Math.Abs(x2 - x0) < 4)
resize = "e";
else if (Math.Abs(y2 - y0) < 4)
resize = "s";
else if (Math.Abs(x0 - x1) < 4)
resize = "w";
else
{
resize = "";
Cursor = Cursors.Arrow;
}
if (resize.IndexOf("n") > -1 || resize.IndexOf("s")>-1)
Cursor = Cursors.SizeNS;
else if (resize.IndexOf("w") > -1 || resize.IndexOf("e") > -1)
Cursor = Cursors.SizeWE;
}
}
private Point GetElementPosition(UIElement e)
{
GeneralTransform gt = e.TransformToVisual(Application.Current.RootVisual as UIElement);
return gt.Transform(new Point(0, 0));
}
void DraggablePanel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if (dragOn)
{
this.Opacity = 1;
this.ReleaseMouseCapture();
dragOn = false;
}
}
void DraggablePanel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
if (e.Handled)
return;
dragOn = true;
beginP = e.GetPosition(null);
this.Opacity *= 0.8;
this.CaptureMouse();
}
}
2) Add the following Style to App.xaml file. Thank desopedr for this suggestion!
<Style TargetType="ContentControl" x:Key="DragAndResize">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ContentControl">
<Canvas>
<controls:DraggablePanel CanResize="True" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<ContentPresenter Content="{TemplateBinding Content}" />
</controls:DraggablePanel>
</Canvas>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
3) Put the following code into PupupWindow.cs to Make a PopupWindow custom control (no PopupWindow.XAML needed).
public class PopupWindow : ContentControl
{
protected Button _CloseButton;
protected Border _ContentContainer;
#region Title
/// <summary>
/// Identifies the Title dependency property.
/// </summary>
public static readonly DependencyProperty TitleProperty = DependencyProperty.Register("Title", typeof(string), typeof(PopupWindow), null);
/// <summary>
/// Gets or sets the Title possible Value of the string object.
/// </summary>
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
#endregion Title
#region TitleBackground
/// <summary>
/// Identifies the TitleBackground dependency property.
/// </summary>
public static readonly DependencyProperty TitleBackgroundProperty = DependencyProperty.Register("TitleBackground", typeof(Brush), typeof(PopupWindow), null);
/// <summary>
/// Gets or sets the TitleBackground possible Value of the Brush object.
/// </summary>
public Brush TitleBackground
{
get { return (Brush)GetValue(TitleBackgroundProperty); }
set { SetValue(TitleBackgroundProperty, value); }
}
#endregion TitleBackground
public void Close()
{
this.Visibility = Visibility.Collapsed;
}
protected override void OnApplyTemplate()
{
base.OnApplyTemplate();
this._CloseButton = this.GetTemplateChild("CloseButton") as Button;
if(this._CloseButton != null)
this._CloseButton.Click += new RoutedEventHandler(_CloseButton_Click);
_ContentContainer = this.GetTemplateChild("ContentContainer") as Border;
if (_ContentContainer != null)
{
_ContentContainer.MouseLeftButtonDown += new MouseButtonEventHandler(_ContentContainer_MouseLeftButtonDown);
}
}
void _ContentContainer_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
e.Handled = true;
}
void _CloseButton_Click(object sender, RoutedEventArgs e)
{
this.Close();
}
}
4) Define Default Style for PopupWindow in the generic.xaml file (Put the following style in the generic .xml file)
<Style TargetType="controls:PopupWindow">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:PopupWindow">
<ContentControl Style="{StaticResource DragAndResize}" Width="{TemplateBinding Width}" Height="{TemplateBinding Height}">
<Border BorderThickness="1" BorderBrush="#999">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="26"/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border Grid.Row="0" Grid.ColumnSpan="2" VerticalAlignment="Stretch" Background="{TemplateBinding TitleBackground}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width="25"/>
&nbs