Reputation: 6147
I'm stuck and not sure why when the user drags the size-gripper, to resize the control on the canvas, that nothing appears to change. However it does fire and print to the console. What am I missing here that's causing it to not resize the item in wpf. I'm not doing anything really complex either. It's pretty straight forward. I'm assuming the issue is somewhere in the ResizeGizmo.cs. I'm guessing for some reason it's not letting me set the size of the contents of the item it's targeting.
Code
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));
}
}
}
Upvotes: 0
Views: 1912
Reputation: 6147
Created a working solution!
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;
}
}
}
Upvotes: 1