在画布上控制更改大小wpf

时间:2016-01-19 14:04:24

标签: c# wpf xaml canvas

我卡住了,并且不确定为什么当用户拖动尺寸抓手,调整画布上的控件大小时,似乎没有任何变化。但它会触发并打印到控制台。我在这里错过了什么导致它不能在wpf中调整项目的大小。我也没做任何非常复杂的事情。它很直接。我假设问题出在ResizeGizmo.cs中的某个地方。我猜是因为某些原因不允许我设定其定位的商品内容的大小。

enter image description here

代码

GraphNodeViewModel.cs

using System.Collections.Generic;
using System.ComponentModel;
using System.Runtime.CompilerServices;

namespace WpfApplication1
{
    public class NodeViewModel : NotifyBase
    {
        // position coordinates
        private double x = 0;
        public double X
        {
            get { return x; }
            set { Set(ref x, value); }
        }

        private double y = 0;
        public double Y
        {
            get { return y; }
            set { Set(ref y, value); }
        }

        public double Z { get; set; }

        private bool isSelected = false;
        public bool IsSelected
        {
            get { return isSelected; }
            set { Set(ref isSelected, value); }
        }

        private string virtualName = "New Node";
        public string VirtualName
        {
            get { return virtualName; }
            set { Set(ref virtualName, value); }
        }

        public NodeViewModel(string virtualName, double x, double y)
        {
            this.virtualName = virtualName;
            this.X = x;
            this.Y = y;
            this.Z = 100; // place top most in z space
        }
    }

    public abstract class NotifyBase : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

        protected void RaisePropertyChanged([CallerMemberName] string propertyName = null)
        {
            if (this.PropertyChanged != null)
                this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
        }

        protected bool Set<T>(ref T field, T value, [CallerMemberName] string propertyName = null)
        {
            if (EqualityComparer<T>.Default.Equals(field, value)) return false;
            field = value;
            RaisePropertyChanged(propertyName);
            return true;
        }
    }
}

ResizeGizmo.cs

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;

namespace WpfApplication1
{
    public class ResizeGizmo : Thumb
    {
        public ResizeGizmo()
        {
            DragDelta += new DragDeltaEventHandler(this.ResizeGizmo_DragDelta);
        }

        private void ResizeGizmo_DragDelta(object sender, DragDeltaEventArgs e)
        {
            Console.WriteLine("Resizing");
            Control item = this.DataContext as Control;

            if (item != null)
            {
                double deltaVertical, deltaHorizontal;

                switch (VerticalAlignment)
                {
                    case VerticalAlignment.Bottom:
                        deltaVertical = Math.Min(-e.VerticalChange,
                            item.ActualHeight - item.MinHeight);
                        item.Height -= deltaVertical;
                        break;
                    case VerticalAlignment.Top:
                        deltaVertical = Math.Min(e.VerticalChange,
                            item.ActualHeight - item.MinHeight);
                        Canvas.SetTop(item, Canvas.GetTop(item) + deltaVertical);
                        item.Height -= deltaVertical;
                        break;
                    default:
                        break;
                }

                switch (HorizontalAlignment)
                {
                    case HorizontalAlignment.Left:
                        deltaHorizontal = Math.Min(e.HorizontalChange,
                            item.ActualWidth - item.MinWidth);
                        Canvas.SetLeft(item, Canvas.GetLeft(item) + deltaHorizontal);
                        item.Width -= deltaHorizontal;
                        break;
                    case HorizontalAlignment.Right:
                        deltaHorizontal = Math.Min(-e.HorizontalChange,
                            item.ActualWidth - item.MinWidth);
                        item.Width -= deltaHorizontal;
                        break;
                    default:
                        break;
                }
            }

            e.Handled = true;
        }
    }
}

MainWindow.xaml

<Window x:Class="WpfApplication1.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:WpfApplication1"
        mc:Ignorable="d"
        Title="MainWindow" Height="600" Width="700"
        Background="sc#1,.01,.01,.01"
        WindowStartupLocation="CenterScreen"
        >

    <Window.DataContext>
        <local:MainWindowViewModel />
    </Window.DataContext>

    <Window.Resources>

        <Style x:Key="SizeGripStyle" TargetType="{x:Type Thumb}">
            <Setter Property="Stylus.IsPressAndHoldEnabled" Value="false"/>
            <Setter Property="Background" Value="#3FFFFFFF"/>
            <Setter Property="BorderThickness" Value="1"/>
            <Setter Property="BorderBrush" Value="White"/>
            <Setter Property="Foreground" Value="White"/>
            <Setter Property="Template">
                <Setter.Value>
                    <ControlTemplate TargetType="{x:Type Thumb}">
                        <Border BorderBrush="{TemplateBinding BorderBrush}" CornerRadius="1" BorderThickness="{TemplateBinding BorderThickness}" Background="{TemplateBinding Background}"/>
                    </ControlTemplate>
                </Setter.Value>
            </Setter>
        </Style>

        <!-- Resize Template -->
        <ControlTemplate x:Key="ResizeGizmoTemplate" TargetType="Control">
            <Grid>
                <local:ResizeGizmo Height="1" Cursor="SizeNS" Margin="0 -4 0 0" VerticalAlignment="Top" HorizontalAlignment="Stretch" Style="{StaticResource SizeGripStyle}"/>
                <local:ResizeGizmo Width="1" Cursor="SizeWE" Margin="-4 0 0 0" VerticalAlignment="Stretch" HorizontalAlignment="Left" Style="{StaticResource SizeGripStyle}"/>
                <local:ResizeGizmo Width="1" Cursor="SizeWE" Margin="0 0 -4 0" VerticalAlignment="Stretch" HorizontalAlignment="Right" Style="{StaticResource SizeGripStyle}"/>
                <local:ResizeGizmo Height="1" Cursor="SizeNS" Margin="0 0 0 -4" VerticalAlignment="Bottom"  HorizontalAlignment="Stretch" Style="{StaticResource SizeGripStyle}"/>
                <local:ResizeGizmo Width="6" Height="6" Cursor="SizeNWSE" Margin="-6 -6 0 0" VerticalAlignment="Top" HorizontalAlignment="Left" Style="{StaticResource SizeGripStyle}"/>
                <local:ResizeGizmo Width="6" Height="6" Cursor="SizeNESW" Margin="0 -6 -6 0" VerticalAlignment="Top" HorizontalAlignment="Right" Style="{StaticResource SizeGripStyle}"/>
                <local:ResizeGizmo Width="6" Height="6" Cursor="SizeNESW" Margin="-6 0 0 -6" VerticalAlignment="Bottom" HorizontalAlignment="Left" Style="{StaticResource SizeGripStyle}"/>
                <local:ResizeGizmo Width="6" Height="6" Cursor="SizeNWSE" Margin="0 0 -6 -6" VerticalAlignment="Bottom" HorizontalAlignment="Right" Style="{StaticResource SizeGripStyle}"/>
            </Grid>
        </ControlTemplate>

        <DataTemplate DataType="{x:Type local:NodeViewModel}">
            <!--Outside border is used to visualize selection-->
            <Border CornerRadius="4" 
                    Padding="20"
                    BorderThickness="1"
                    BorderBrush="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=BorderBrush}"
                    Background="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ListBoxItem}}, Path=Background}">
                <Grid>
                    <Border>
                        <Grid>
                            <Control Template="{StaticResource ResizeGizmoTemplate}"/>
                            <Border Background="LightBlue" CornerRadius="4" Padding="10">
                                <TextBox Text="This is cool"/>
                            </Border>
                        </Grid>
                    </Border>
                </Grid>
            </Border>
        </DataTemplate>

    </Window.Resources>

    <Grid>
        <!-- visual Nodes and Connections -->
        <ListBox x:Name="listBox" ItemsSource="{Binding GraphNodes}" 
                 SelectionMode="Extended" 
                 Background="Transparent">

            <ListBox.ItemsPanel>
                <ItemsPanelTemplate>
                    <Canvas />
                </ItemsPanelTemplate>
            </ListBox.ItemsPanel>

            <ListBox.ItemContainerStyle>
                <Style TargetType="ListBoxItem" >
                    <Setter Property="Canvas.Left" Value="{Binding X}" />
                    <Setter Property="Canvas.Top" Value="{Binding Y}" />
                    <Setter Property="Panel.ZIndex" Value="{Binding Z}" />
                    <Setter Property="IsSelected" Value="{Binding IsSelected}" />
                    <Setter Property="Template">
                        <Setter.Value>
                            <ControlTemplate TargetType="{x:Type ListBoxItem}">
                                <ContentPresenter/>
                                <ControlTemplate.Triggers>
                                    <Trigger Property="IsSelected" Value="True" >
                                        <Setter Property="Background" Value="sc#0.3,1,1,1"/>
                                        <Setter Property="BorderBrush" Value="White"/>
                                    </Trigger>
                                </ControlTemplate.Triggers>
                            </ControlTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListBox.ItemContainerStyle>

            <ListBox.Resources>
                <Style TargetType="{x:Type ListBoxItem}">
                    <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                </Style>
            </ListBox.Resources>

        </ListBox>

        <!-- This Canvas is used to render a drag selection rectangle -->
        <Canvas x:Name="dragSelectionCanvas" Visibility="Collapsed" >
            <Border 
                x:Name="dragSelectionBorder"
                BorderBrush="White"
                BorderThickness="1"
                Background="sc#0.1,1,1,1"
                CornerRadius="2"
                Opacity=".5"
                IsHitTestVisible="False"
                />
        </Canvas>

    </Grid>
</Window>

MainWindowViewModel.cs

using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace WpfApplication1
{
    public class MainWindowViewModel : NotifyBase
    {
        private ObservableCollection<NodeViewModel> graphNodes = new ObservableCollection<NodeViewModel>();
        public ObservableCollection<NodeViewModel> GraphNodes { get { return graphNodes; } }

        public MainWindowViewModel()
        {
            // Populate the view model with some example data.
            graphNodes.Add(new NodeViewModel("Type here", 50, 50));
            graphNodes.Add(new NodeViewModel("Type in another box here", 180, 150));
            graphNodes.Add(new NodeViewModel("This is fun", 160, 70));
            graphNodes.Add(new NodeViewModel("Why is this working", 320, 230));
            graphNodes.Add(new NodeViewModel("ABC", 20, 170));
        }
    }

}

1 个答案:

答案 0 :(得分:0)

创建了一个可行的解决方案!

using System;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Media;

namespace WpfApplication1
{
    public class ResizeGizmo : Thumb
    {
        public ResizeGizmo()
        {
            DragDelta += new DragDeltaEventHandler(this.ResizeGizmo_DragDelta);
        }

        private void ResizeGizmo_DragDelta(object sender, DragDeltaEventArgs e)
        {
            float MinSize = 70;

            NodeViewModel node = this.DataContext as NodeViewModel;
            var element = sender as FrameworkElement;


            if (node != null)
            {
                double deltaVertical, deltaHorizontal;

                switch (VerticalAlignment)
                {
                    case VerticalAlignment.Bottom:
                        deltaVertical = Math.Min(-e.VerticalChange, node.Height - MinSize);
                        node.Height -= deltaVertical;
                        break;
                    case VerticalAlignment.Top:
                        deltaVertical = Math.Min(e.VerticalChange, node.Height - MinSize);
                        node.Y += deltaVertical;
                        node.Height -= deltaVertical;
                        break;
                    default:
                        break;
                }
                switch (HorizontalAlignment)
                {
                    case HorizontalAlignment.Left:
                        deltaHorizontal = Math.Min(e.HorizontalChange, node.Height - MinSize);
                        node.X += deltaHorizontal;
                        node.Width -= deltaHorizontal;
                        break;
                    case HorizontalAlignment.Right:
                        deltaHorizontal = Math.Min(-e.HorizontalChange, node.Height - MinSize);
                        node.Width -= deltaHorizontal;
                        break;
                    default:
                        break;
                }
            }

            e.Handled = true;
        }
    }
}