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"/>
</Grid.ColumnDefinitions>
<TextBlock x:Name="Title" Text="{TemplateBinding Title}" Margin="5 0 5 0" Foreground="White"></TextBlock>
<Button x:Name="CloseButton" Grid.Column="1" Style="{StaticResource CloseButton}"/>
</Grid>
</Border>
<Border Grid.Row="1" Margin="1 0 1 1" x:Name="ContentContainer" Background="{TemplateBinding Background}">
<ContentPresenter Content="{TemplateBinding Content}" />
</Border>
</Grid>
</Border>
</ContentControl>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
5) Now you can test PopupWindow control you just created. Create a PopupTest user control with the following XAML, remember to change the namespace of controls to your namespace. Run the test. If it works, you can replace the TextBlock with any content control you want.
<UserControl x:Class="PopupTest"
xmlns="http://schemas.microsoft.com/client/2007"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="clr-namespace:MySilverlight.Controls;assembly=MySilverlight.Controls"
xmlns:data="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"
>
<Grid x:Name="LayoutRoot" Background="White">
<controls:PopupWindow Title="Popup Window Test" Background="Beige" Width="300" Height="300">
<controls:PopupWindow.TitleBackground>
<LinearGradientBrush EndPoint="0.5,1"
StartPoint="0.5,0">
<GradientStop Color="#FF880000"
Offset="0" />
<GradientStop Color="#FFD64300"
Offset="1" />
</LinearGradientBrush>
</controls:PopupWindow.TitleBackground>
<!--Put window content here -->
<TextBlock Text="Window Content here"></TextBlock>
</controls:PopupWindow>
</Grid>
</UserControl>
Hope this helps.
sladapter
Software Engineer
Aprimo, Inc
Please remember to mark the replies as answers if they answered your question