Canvas 控件

 

C# wpf 实现Canvas内控件拖动

 实现方式一:

1.注册鼠标事件

拖动的控件需要注册3个鼠标事件分别是,鼠标按下、鼠标移动、鼠标弹起。
以Button为例

 

<Button   PreviewMouseDown="Button_MouseDown" 
          PreviewMouseMove="Button_MouseMove" 
          PreviewMouseUp="Button_MouseUp"> </Button>

 

2.记录位置

在鼠标按下事件中记录位置。记录位置时需要判断属性值是否为NAN,如果为NAN则记录为0。

 

//鼠标是否按下
bool _isMouseDown = false;
//鼠标按下的位置
Point _mouseDownPosition;
//鼠标按下控件的位置
Point _mouseDownControlPosition;
//鼠标按下事件
private void Button_MouseDown(object sender, MouseButtonEventArgs e)
{
    var c = sender as Control;
    _isMouseDown = true;
    _mouseDownPosition = e.GetPosition(this);
    _mouseDownControlPosition = new Point(double.IsNaN(Canvas.GetLeft(c))? 0:Canvas.GetLeft(c),double.IsNaN(Canvas.GetTop(c)) ? 0 : Canvas.GetTop(c) );
    c.CaptureMouse();
}

 

3.跟随鼠标移动

鼠标按下后移动鼠标,控件需要跟随鼠标移动。直接计算移动距离,设置Canvas.Left和Canvas.Top即可。

 

private void Button_MouseMove(object sender, MouseEventArgs e)
{
    if (_isMouseDown)
    {
        var c = sender as Control;
        var pos = e.GetPosition(this);
        var dp = pos - _mouseDownPosition;
        Canvas.SetLeft(c, _mouseDownControlPosition.X+ dp.X);
        Canvas.SetTop(c, _mouseDownControlPosition.Y + dp.Y);
    }
}

 

 

4.恢复标识

鼠标弹起后需要恢复标识,让控件不再跟随鼠标移动。

 

private void Button_MouseUp(object sender, MouseButtonEventArgs e)
{          
   var c = sender as Control;
   _isMouseDown = false;
   c.ReleaseMouseCapture();
} 

 

二、示例

示例代码:

 

<Window x:Class="WpfControlMove.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
        xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
        xmlns:local="clr-namespace:WpfControlMove"
        mc:Ignorable="d"
        Title="MainWindow" Height="360" Width="640">
    <Canvas>
        <Button Width="120" Height="50" Content="移动"   PreviewMouseDown="Button_MouseDown" PreviewMouseMove="Button_MouseMove" PreviewMouseUp="Button_MouseUp"> </Button>
    </Canvas>
</Window>

 

  实现方式二:

矩形_rectangle在Canvas中
 /// 移动矩形
 MouseDragElementBehavior dragBehavior = new  MouseDragElementBehavior();
 dragBehavior.Attach(_rectangle);
 dragBehavior.DragFinished += onDragFinished;

在Canvas中设置控件坐标

Label label = new Label
{
    Content = "测试",
    FontSize = 14,
    Foreground = new SolidColorBrush((Color)ColorConverter.ConvertFromString("#FF0000"))
};
 
Canvas.SetTop(label, 10.9);//在c#后台代码中动态设置
Canvas.SetLeft(label, 20.39);
 
printArea.Children.Add(label);

这种方式适合动态增加控件的页面。


动态创建控件

1.容器控件.RegisterName("Name",要注册的控件)   //注册控件

2.容器控件.FindName("Name") as  控件类型            //找到控件并转换成相应类型

注意:仅通过 控件.Name来设置是不能通过FindName来找到控件的,必须注册
动态删除控件
1.容器控件.Children.Remove(控件)                           //移除控件

2.容器控件.UnregisterName("Name")                       //取消注册

其它设置

1.控件.SetValue(Grid.RowProperty, 0);                    //设置控件在Grid面板中的行数
   控件.SetValue(Grid.ColumnProperty, 1);               //设置控件在Grid面板中的列数

2.Canvas.SetLeft("控件名", 50);                                //设置控件在Canvas面板中的横坐标
   Canvas.SetTop("控件名", 50);                                //设置控件在Canvas面板中的纵坐标

 

mvvm 模式下,Canvas 实现动态添加元素

Subjectview

 

 <ItemsControl Margin="0,0,0,20" ItemsSource="{Binding Balloons}" x:Name="canvasBackground" Grid.Column="1" Grid.Row="1" Grid.ColumnSpan="2">
     <ItemsControl.ItemsPanel>
         <ItemsPanelTemplate>
             <!-- IsItemsHost=true表示子元素将显示在此容器中。 在SubjectViewModel中增删改Balloons集合对象就可以设置 Canvas中元素的。-->
             <Canvas IsItemsHost="True"/>
         </ItemsPanelTemplate>
     </ItemsControl.ItemsPanel>
     <ItemsControl.ItemContainerStyle>
         <Style>
             <!-- Canvas.Left\Canvas.Top对应 ItemViewModel中的X\Y属性,-->
             <Setter Property="Canvas.Left" Value="{Binding X}"/>
             <Setter Property="Canvas.Top" Value="{Binding Y}"/>
         </Style>
     </ItemsControl.ItemContainerStyle>


 </ItemsControl>

 ItemViewModel

 internal partial class BalloonViewModel : ObservableObject 
  {
///其他代码
    /// <summary>
 /// 坐标点
 /// </summary>
 /// 
 [ObservableProperty]
 public double? x;
 [ObservableProperty]
 public double? y;
}

SubjectViewModel

  internal partial class SubjectViewModel: ObservableObject
  {
///其他代码
    /// <summary>
 /// 元素集合
 /// </summary>
 /// 
 [ObservableProperty]
 ObservableCollection<BalloonViewModel>? balloons=new();
}

 

只需少量更改即可使用<Canvas IsItemsHost=“True” />,    IsItemsHost=true表示子元素将显示在此容器中。

Canvas 复杂矢量图形布局

如果希望Path的各个部分使用不同的颜色,就需要创建彼此独立的Path对象。 此时就需要使用View+Canvas+path的组合方式 来设计复杂的矢量图形。

注意必须给canvas设置一个初始的 Width Height的,否则无法显示。

 

     <Viewbox  Stretch="Uniform"  >
         <Canvas Width="80" Height="220" >
             <!--球体-->
             <Path  Canvas.Left="0" Canvas.Top="0"  Fill="{Binding BalloonColor}"    Data="M57.078,140.071h6.175L69,153l-18.054-.946ZM61,0c33.689,0,61,31.34,61,70s-27.311,70-61,70S0,108.66,0,70,27.311,0,61,0Z"  />
             <!--反光-->
             <Path   Fill="{Binding  ReflectLight}" Data="M33.978,35.095c6.638,1.091,10.462,11.335,8.542,22.881S33.66,78,27.022,76.905,16.56,65.57,18.48,54.025,27.34,34,33.978,35.095Z"   />
             <!--线条-->
             <Path   StrokeThickness="4" Stroke="{Binding  Line}" Data="M62,152c-4.764,15.394-5.243,29.971,0,43,2.406,5.98,7.875,14.606,14,23,4.172,5.717,6.546,9.83,8,16,3.84,16.294-3.737,52.7-11,67" />
         </Canvas>
     </Viewbox>

 

 

posted @ 2024-03-16 03:49  小林野夫  阅读(158)  评论(0编辑  收藏  举报
原文链接:https://www.cnblogs.com/cdaniu/