2013-04-01 5 views
13

Tôi cần một điều khiển ngón tay cái có thể được định kích thước bằng chuột. Khi người dùng di chuột qua một trong các đầu, con trỏ kích thước sẽ được hiển thị và khi người dùng nhấp và kéo phần cuối của điều khiển, nó sẽ được kích thước lại.Sử dụng WPF Tôi đang tìm cách tạo điều khiển Thumb bằng cách sử dụng chuột để kéo cạnh

Tôi bắt đầu nghĩ rằng tôi nên tạo một điều khiển tùy chỉnh được tạo từ ba điều khiển ngón tay cái. Sẽ có một ngón tay cái chính và sau đó một cho mỗi đầu sẽ xử lý việc tái kích thước, nhưng tôi quyết định đó không phải là một giải pháp tốt.

Tôi nghĩ rằng một cách tiếp cận tốt hơn là sử dụng một điều khiển Thumb duy nhất và sau đó có một kích thước lại Adorner bật lên ở phần cuối của điều khiển chuột lơ lửng trên. Với cách tiếp cận này, làm thế nào bạn có thể phát hiện chuột đang lơ lửng trên một vùng cụ thể của điều khiển? Ví dụ về cách thực hiện việc này hoặc bất kỳ trợ giúp nào sẽ được đánh giá cao.

+1

Tôi đã sử dụng mẫu này trong quá khứ, nhưng bạn cần phải nhấp vào tầm kiểm soát. Có lẽ bạn có thể điều chỉnh nó để đăng ký các sự kiện di chuột (hittest hoặc một cái gì đó) http://denisvuyka.wordpress.com/2007/10/15/wpf-simple-adorner-usage-with-drag-and-resize-operations/ –

Trả lời

22

Dưới đây là một trong tôi đã thực hiện một thời gian trước đây, nó cho phép MoveResize, nhưng bạn có thể loại bỏ logic Move và nó sẽ làm việc tốt (phong cách vẫn còn một chút lộn xộn, nhưng nó hoạt động khá tốt)

nó dựa trên ContentControl để bạn có thể thêm bất kỳ Element trong và Move/Resize trên Canvas, Nó sử dụng 3 Adorners, một cho Resize, một cho Move và một để hiển thị thông tin (kích thước hiện tại)

Dưới đây là một ví dụ làm việc đầy đủ nếu bạn muốn kiểm tra/sử dụng/sửa đổi/cải thiện :)

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> 

Kết quả:

enter image description hereenter image description here

Với nội dung bên trong (Nút)

enter image description here

Xin lỗi con trỏ không hiển thị khi sử dụng SnipTool

+1

Câu trả lời xuất sắc !! +1 –

+0

Cảm ơn sự giúp đỡ của bạn. Từ ví dụ của bạn, tôi đã có thể làm cho mọi thứ hoạt động như tôi cần. – user1401827