Page view counter
Draggable window or datagrid
Last post 11-15-2008 1:28 AM by hoangtuit. 96 replies.
Sort Posts:
03-24-2008 7:54 AM
Draggable window or datagrid

Hi, how can i implement one Draggable window, one that  i can put inside it all the controls i want like a normal page, and then have multiple windows on my application.

 For example, i m trying to make this, by makin a user control, with only a white rectangle, so i add the user control to my parent page, but i can't implement the drag and drop. Do i have to implemant it on my user control xaml, or in the applications when i call my user control? 

 is it possible to have a datagrid in this user control and drag it around the browser?

 Thanks in advance

Rui Marinho

Rui-Marinho

Loading...
Joined on 03-19-2008
Posts 89
03-24-2008 9:32 AM
Re: Draggable window or datagrid

Here is a DragDropPanel I use. You can put any control into this Panel so it will become Draggable. Remember to put the DragDropPanel in a Canvas.

 

 public class DragDropPanel : Canvas
    {
        Point beginP;
        Point currentP;
        bool dragOn = false;
        public DragDropPanel() : base()
        {
            this.MouseLeftButtonDown += new MouseButtonEventHandler(DragDropPanel_MouseLeftButtonDown);
            this.MouseLeftButtonUp += new MouseButtonEventHandler(DragDropPanel_MouseLeftButtonUp);
            this.MouseMove += new MouseEventHandler(DragDropPanel_MouseMove);
            this.Cursor = Cursors.Hand;
        }

        void DragDropPanel_MouseMove(object sender, MouseEventArgs e)
        {
            if (dragOn)
            {
                currentP = e.GetPosition(null);
                double x0 = System.Convert.ToDouble(this.GetValue(Canvas.LeftProperty));
                double y0 = System.Convert.ToDouble(this.GetValue(Canvas.TopProperty));
                this.SetValue(Canvas.LeftProperty, x0 + currentP.X - beginP.X);
                this.SetValue(Canvas.TopProperty, y0 + currentP.Y - beginP.Y);
                beginP = currentP;
            }
        }

        void DragDropPanel_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
        {
            if (dragOn)
            {
                this.Opacity *= 2;
                this.ReleaseMouseCapture();
                dragOn = false;
            }
        }

        void DragDropPanel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            System.Windows.FrameworkElement c = sender as System.Windows.FrameworkElement;
            dragOn = true;
            beginP = e.GetPosition(null);
            c.Opacity *= 0.5;
            c.CaptureMouse();
        }        
    }

sladapter
Software Engineer
Aprimo, Inc

Please remember to mark the replies as answers if they answered your question

sladapter

Loading...
Joined on 03-05-2008
Indiana, US
Posts 2,691
03-24-2008 10:48 AM
Re: Draggable window or datagrid

Sorry , i understand the class, but i don't understand how i will use it in a user control. Because the class is

public class DragDropPanel : User control

Rui-Marinho

Loading...
Joined on 03-19-2008
Posts 89
03-24-2008 12:24 PM
Marked as Answer
Re: Draggable window or datagrid

Put the code I posted above into a DragDropPanel.cs into your project. No XAML is needed for that file. Then create a Silverlight UserControl called DraggableTest in your project. Put the following XAML into it. Change the name space for "controls" to the name space of your DraggablePanel object. Run it you can see it work. You can switch different content control in the DragDropPanel so they become draggable..
 

<UserControl x:Class="DraggbleTest"
    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"
    >

    <Grid x:Name="LayoutRoot" >
        <Grid.RowDefinitions>
            <RowDefinition></RowDefinition>
            <RowDefinition></RowDefinition>
        </Grid.RowDefinitions>
        <TextBlock Text="Fixed Text"></TextBlock>
        
        <Canvas Grid.RowSpan="2" Grid.Row="1">
            <controls:DragDropPanel>                                   
                <TextBlock Text="Draggable Text"></TextBlock>                                         
            </controls:DragDropPanel>
        </Canvas>
    </Grid>
</UserControl>

sladapter
Software Engineer
Aprimo, Inc

Please remember to mark the replies as answers if they answered your question

sladapter

Loading...
Joined on 03-05-2008
Indiana, US
Posts 2,691
03-25-2008 12:39 PM
Re: Re: Draggable window or datagrid

thanks, it works fine :)

 

Greetings

Rui

Rui-Marinho

Loading...
Joined on 03-19-2008
Posts 89
03-25-2008 9:28 PM
Re: Re: Draggable window or datagrid

Hi sladapter,

Nice to share, works fine thanks :)

As you say the control must be in a Canvas, so to prevent missing that I think creating a style can be helpful. Canvas doesn't have a template property so I put the draggableControl in a ContenControl.

<Style TargetType="ContentControl" x:Key="DraggableContent">
      <Setter Property="Template">
        <Setter.Value>
          <ControlTemplate TargetType="ContentControl">
            <Canvas>
              <custom:DraggableCanvas>
                <ContentPresenter Content="{TemplateBinding Content}" />
              </custom:DraggableCanvas>
            </Canvas>
          </ControlTemplate>
        </Setter.Value>
      </Setter>
    </Style>

You can put your ContentControl where you want, not necessary a canvas

<ContentControl Style="{StaticResource DraggableContent}">
     ...controls...
</ContentControl>:

desopedr
 

desopedr

Loading...
Joined on 02-15-2008
Switzerland, Valais
Posts 31
03-26-2008 6:53 AM
Re: Re: Draggable window or datagrid
Sory desopedr but it dosen't work for me.. the browser crash when using
Rui-Marinho

Loading...
Joined on 03-19-2008
Posts 89
03-26-2008 7:23 AM
Re: Re: Draggable window or datagrid

Ola Rui,

Can you tell me what you have done and what is the error ? Maybe could I help you.

Do you copy/paste my style and use it whitout changes ? Don't forget to change the following lines if you use the sladapter's original code and my style :

replace : 

<custom:DraggableCanvas>
      <ContentPresenter Content="{TemplateBinding Content}" />
</custom:DraggableCanvas>

by :

<controls:DragDropPanel>
      <ContentPresenter Content="{TemplateBinding Content}" />
</controls:DragDropPanel>

 

Hope this helps.

desopedr 

 

desopedr

Loading...
Joined on 02-15-2008
Switzerland, Valais
Posts 31
03-26-2008 7:39 AM
Re: Re: Draggable window or datagrid

i changed the code so it fit my controls, but when i run it crash the browser, no error output :(

 I have put static resource in app.xaml.

 Then i trade the canvas that i add in my user control, for the contentcontrol with the style of app.xaml

 when runnig the ie dose't respond!

 Rui

Rui-Marinho

Loading...
Joined on 03-19-2008
Posts 89
03-26-2008 10:41 AM
Re: Re: Draggable window or datagrid

 hmm you can download the source here, hope you could find the mistake comparing the code

desopedr

Loading...
Joined on 02-15-2008
Switzerland, Valais
Posts 31
03-26-2008 11:07 AM
Re: Re: Draggable window or datagrid

I download the cod and it seems that the only difrence is that i m  using it in a user control, and adding it on the page.xaml from cs code. this is my user control that works

<UserControl x:Class="iffiretv.datagrid"

xmlns:my="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

xmlns="http://schemas.microsoft.com/client/2007"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:controls="clr-namespace:iffiretv"

>

<Grid x:Name="LayoutRoot" >

<Canvas>

<controls:DragDropPanel>

<my:DataGrid

Height="400"

Width="400"

AutoGenerateColumns="True"

GridlinesVisibility="Horizontal"

HeadersVisibility="Column"

VerticalAlignment="Stretch"

RowBackground="Cornsilk"

AlternatingRowBackground="LemonChiffon"

ColumnWidth="85"

RowHeight="30"

IsReadOnly="False"

CanUserResizeColumns="True"

Margin=" 0,0,0,0"

x:Name="dataGrid" />

</controls:DragDropPanel>

</Canvas>

</Grid>

</UserControl>

 

if i try with content panel like this

<UserControl x:Class="iffiretv.datagrid"

xmlns:my="clr-namespace:System.Windows.Controls;assembly=System.Windows.Controls.Data"

xmlns="http://schemas.microsoft.com/client/2007"

xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"

xmlns:controls="clr-namespace:iffiretv"

>

<Grid x:Name="LayoutRoot" >

<ContentControl Style="{StaticResource DraggableContent}">

<my:DataGrid

Height="400"

Width="400"

AutoGenerateColumns="True"

GridlinesVisibility="Horizontal"

HeadersVisibility="Column"

VerticalAlignment="Stretch"

RowBackground="Cornsilk"

AlternatingRowBackground="LemonChiffon"

ColumnWidth="85"

RowHeight="30"

IsReadOnly="False"

CanUserResizeColumns="True"

Margin=" 0,0,0,0"

x:Name="dataGrid" />

</ContentControl>

</Grid>

</UserControl>

 it dosent work... it dosen't add the grid to the page.xaml

 i will look further to try solving it :)

but thanks for the help.

 Rui

Rui-Marinho

Loading...
Joined on 03-19-2008
Posts 89
03-26-2008 11:25 AM
Re: Re: Re: Draggable window or datagrid

it's working.. i just added assembly=iffiretv in the reference

 thanks :)

thais is great to put controls and windows.. i will now try to resize the controls when browser resize.. because if you drag on control and the resize the window it will be sometimes of the browser :/

 thanks for all the help..

Rui-Marinho

Loading...
Joined on 03-19-2008
Posts 89
03-26-2008 12:07 PM
Re: Re: Re: Draggable window or datagrid

Another question.

 I m trying to simulate some windows in my silverlight, so we can drag and drop.. inside the window i want to put one datagrid, but when i click the left button on the grid i don't want to move it, i just want to move when i click the control outside de grid.

 Well i m trying to get the framework element of the dragdroppanel class when we click the mouse left down, so i will test if it is a grid or not,  like this

void DragDropPanel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

{

System.Windows.
FrameworkElement c = sender as System.Windows.FrameworkElement;

 

string data = c.FindName("dataGrid").ToString();dragOn = true;

...

but it dosent seem to work.. does anyone now how i can see if im click in the grid or not? can i go to the canvas and see the childrens ? 

 Greetings

Rui 

 

 

 

Rui-Marinho

Loading...
Joined on 03-19-2008
Posts 89
03-26-2008 1:26 PM
Re: Re: Re: Draggable window or datagrid

 Rui,

Add a new line of code in the DragDropPanel_MouseLeftButtonDown function

void DragDropPanel_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

{

    if (e.Handled == true)
                return;

  ...

}

In your DataGrid_MouseLeftButtonDown handle add another line:

 void DataGrid_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)

{

    // your code

    e.Handled = true;

This way the mousedown event won't get bubbled up. 

 


 

 

sladapter
Software Engineer
Aprimo, Inc

Please remember to mark the replies as answers if they answered your question

sladapter

Loading...
Joined on 03-05-2008
Indiana, US
Posts 2,691
03-26-2008 2:18 PM
Re: Re: Re: Draggable window or datagrid
nice it works fine :) thank you alot.. now working on resizes...
Rui-Marinho

Loading...
Joined on 03-19-2008
Posts 89
03-26-2008 2:29 PM
Re: Re: Re: Draggable window or datagrid

 OK,  here I put up a Draggble Window Test page. You only can drag the window when mouse is on the TitleBar area. You can certainly warp this code to make a  DraggableWindow control.

 

 <UserControl x:Class="DraggbleTest"
    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">  

           
        <ContentControl x:Name="Popup" Style="{StaticResource DraggableConent}" >                
                <Grid Width="400" Height="400">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="25"/>                           
                        <RowDefinition/>
                    </Grid.RowDefinitions>                  
                    <Border Grid.Row="0" Grid.ColumnSpan="2" BorderThickness="1" BorderBrush="#ccc" Background="BlueViolet">
                        <Grid>
                            <Grid.ColumnDefinitions>
                                <ColumnDefinition/>
                                <ColumnDefinition Width="25"/>
                            </Grid.ColumnDefinitions>                      
                            <TextBlock Margin="5 0 5 0" Foreground="White">Popup Window</TextBlock>
                            <Button x:Name="CloseButton" Grid.Column="1" Style="{StaticResource CloseButton}" Click="CloseButton_Click"/>                          
                        </Grid>
                    </Border>
                    <Border Grid.Row="1" BorderThickness="1" BorderBrush="#ccc" MouseLeftButtonDown="Border_MouseLeftButtonDown">
                        <data:DataGrid Grid.Row="1" x:Name="MyDataGrid" AutoGenerateColumns="True" HeadersVisibility="Column">                                                          
                        </data:DataGrid>
                    </Border>
                </Grid>       
        </ContentControl>
    </Grid>
</UserControl>

 Code Behind:

public partial class DraggbleTest: UserControl
    {
        public DraggbleTest()
        {
            InitializeComponent();           
        }
   
        private void Border_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            e.Handled = true;
        }

        private void CloseButton_Click(object sender, RoutedEventArgs e)
        {
            this.Popup.Visibility = Visibility.Collapsed;
        }
    }

 

CloseButton Style: Put it in App.xaml

<!-- CloseButton Style -->
        <Style x:Key="CloseButton" TargetType="Button">
            <Setter Property="Width" Value="25" />
            <Setter Property="Height" Value="25" />
            <Setter Property="HorizontalAlignment" Value="Right" />
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="Button">
                        <Border Width="22" Height="22" CornerRadius="15">
                            <TextBlock
                                Foreground="#222"
                                Text="r"
                                FontSize="11"
                                FontFamily="Webdings"
                                TextAlignment="Center"
                                VerticalAlignment="Center"
                            >                               
                            </TextBlock>
                            <Border.Background>
                                <RadialGradientBrush GradientOrigin="0.3, 0.3">
                                    <GradientStop Color="#fff" Offset="0.15"></GradientStop>
                                    <GradientStop Color="#777" Offset="1"></GradientStop>
                                </RadialGradientBrush>
                            </Border.Background>
                        </Border>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

sladapter
Software Engineer
Aprimo, Inc

Please remember to mark the replies as answers if they answered your question

sladapter

Loading...
Joined on 03-05-2008
Indiana, US
Posts 2,691
03-27-2008 6:20 AM
Re: Re: Re: Draggable window or datagrid

very nice slapadapter... just what i needed...

Can you give me an ideia how to make it resizble now?

 

Thanks

Rui

Rui-Marinho

Loading...
Joined on 03-19-2008
Posts 89
03-27-2008 9:36 AM
Re: Re: Re: Draggable window or datagrid

 You want to make it like a real window so user can resize it as they want? I do not have code for it. But I'll try.

sladapter
Software Engineer
Aprimo, Inc

Please remember to mark the replies as answers if they answered your question

sladapter

Loading...
Joined on 03-05-2008
Indiana, US
Posts 2,691
03-27-2008 3:28 PM
Re: Re: Re: Draggable window or datagrid

 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