I'm trying to create an animation by using for loop when I load into page by increasing it's width and position. My problem is that Application.Current.MainWindow.Width in the Page_Loaded for loop doesn't work. While it works perfectly when leaving the page. My Code:
private void Page_Loaded(object sender, RoutedEventArgs e)
{
for (double i = 0; i < 50; i++)
{
Application.Current.MainWindow.Left = Application.Current.MainWindow.Left - 2;
Application.Current.MainWindow.Width = Application.Current.MainWindow.Width + 4;
}
}
private void Home_Click(object sender, RoutedEventArgs e)
{
NavigationService.GoBack();
for (double i = 0; i < 50; i++)
{
Application.Current.MainWindow.Left = Application.Current.MainWindow.Left + 2;
Application.Current.MainWindow.Width = Application.Current.MainWindow.Width - 4;
}
}
When I go to the intended page, my window just moves to the left but the width doesn't increase until the page is completely loaded and it just jumps to the final width rather than animate that. When I leave the page, both my window and width are being changed together.
Is there some limitation when setting the width under Page_Loaded? If so, how can I get over this?
XAML Settings
mc:Ignorable="d"
Loaded="Page_Loaded"
Title="DatabaseViewer">
<Grid >
<TextBlock Height="75" Margin="65,20,65,0" Text="Solder Paste Database" TextAlignment="Center" FontSize="30" VerticalAlignment="Top" />
<Button Margin="0,17,30,0" Width="50" Height="50" FontSize="20" HorizontalAlignment="Right" VerticalAlignment="Top" BorderThickness="0" Click="Export_Click"
Style="{DynamicResource SquareButtonStyle}" ToolTip="Export to Excel">
<StackPanel>
<Rectangle Width="40" Height="40" HorizontalAlignment="Center" VerticalAlignment="Center" Fill="Green">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Uniform" Visual="{StaticResource appbar_office_excel}" />
</Rectangle.OpacityMask>
</Rectangle>
</StackPanel>
</Button>
<DataGrid Name="dbGrid" Width="750" Height="340" VerticalAlignment="Bottom" HorizontalAlignment="Center" Margin="0,0,0,20"
HorizontalContentAlignment="Center" IsReadOnly="True" PreviewKeyDown="dbGrid_KeyDown" GridLinesVisibility="All"
BorderBrush="Black" BorderThickness="1" SelectionChanged="dbGrid_SelectionChanged" >
</DataGrid>
<Grid HorizontalAlignment="Right" VerticalAlignment="Top" Margin="0,70,25,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="115"/>
<ColumnDefinition Width="40"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
</Grid.RowDefinitions>
<Label FontSize="14" FontWeight="Bold" Grid.Column="0" Grid.Row="0" Content="Selected Count: " HorizontalAlignment="Right" VerticalAlignment="Bottom"/>
<Label FontSize="14" Grid.Column="1" Grid.Row="0" Content="0" HorizontalAlignment="Left" VerticalAlignment="Bottom" x:Name="selectedCount" />
</Grid>
<Grid HorizontalAlignment="Left" VerticalAlignment="Top" Margin="25,70,0,0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="150"/>
<ColumnDefinition Width="100"/>
<ColumnDefinition Width="100"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="26" />
</Grid.RowDefinitions>
<TextBox Width="150" FontSize="14" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Right" x:Name="TB" ToolTip="Column Name = Value [& Column Name = Value]"/>
<Button Margin="10,0,0,0" Padding="0,0,0,0" FontSize="14" Width="80" Content="Filter" Grid.Column="1" Grid.Row="0" VerticalContentAlignment="Center"
HorizontalAlignment="Left" VerticalAlignment="Bottom" Click="filter_click" />
<Label Grid.Column="2" x:Name="filterLabel" Content="Invalid Search" Foreground="Red" FontWeight="Bold"/>
</Grid>
<Button Margin="20,27,0,0" Width="30" Height="30" FontSize="18" HorizontalAlignment="Left" Click="Home_Click" VerticalAlignment="Top" BorderThickness="0" UseLayoutRounding="True" BorderBrush="White"
Style="{DynamicResource MetroCircleButtonStyle}" >
<Rectangle Width="30" Height="30"
Fill="#41b1ff">
<Rectangle.OpacityMask>
<VisualBrush Stretch="Uniform" Visual="{DynamicResource appbar_arrow_left}" />
</Rectangle.OpacityMask>
</Rectangle>
</Button>
</Grid>
Using explicit code to change dimensions in a loop will most likely result in batching as you have seen. Not to mention you are blocking the UI during all this so I am rather surprised you saw anything change during the loop.
The correct way to essentially animate is to use WPF Storyboards. Here you would define your start and end conditions, what it is you want to animate (width, Left) and how long the animation should run for and tell it to play. Storyboards then run without you needing to do anything more. You can define it in code or straight-up XAML.
Tell me more...
MickyD is right, a Storyboard is the best bet in this situation. Though I can achieve what you want through looping in the code-behind, the result is often buggy as you have seen. In your situation for example you would want to make a DoubleAnimation for expansion in your Windows resources.
XAML
<Window.Resources>
<Storyboard x:Key="sb2">
<DoubleAnimation Storyboard.TargetName="myWindowName" Storyboard.TargetProperty="Width" From="500" To="1200" Duration="0:0:3" AutoReverse="False"/>
<DoubleAnimation Storyboard.TargetName="myWindowName" Storyboard.TargetProperty="Left" From="500" To="200" Duration="0:0:3" AutoReverse="False"/>
</Storyboard>
</Window.Resources>
Then in your Window (or Controls) Loaded event
private void myWindowName_Loaded(object sender, RoutedEventArgs e)
{
//Reference System.Windows.Media.Animation;
Storyboard storyBoardIn = (Storyboard)TryFindResource("sb2");
storyBoardIn.Begin();
}
You will obviously need to change your storyboard params in XAML to acheive the exact thing you want. This solution is less code and more reliable in WPF. Best of luck!
Related
I tried to make a new UWP app just to test things out, but now I'm stuck with this exception:
System.AccessViolationException: 'Attempted to read or write protected memory.
This is often an indication that other memory is corrupt.'
All I did after making new Solution, was to make few more pages and added this to the App() in order to achieve global back button:
public App()
{
this.InitializeComponent();
this.Suspending += OnSuspending;
var currentView = SystemNavigationManager.GetForCurrentView();
currentView.AppViewBackButtonVisibility = AppViewBackButtonVisibility.Visible;
Frame rootFrame = Window.Current.Content as Frame;
}
private void App_BackRequested(object sender, Windows.UI.Core.BackRequestedEventArgs e)
{
e.Handled = On_BackRequested();
}
And now, every time, it goes to this:
var currentView = SystemNavigationManager.GetForCurrentView();
I get this exception. I'm running out of ideas. Does anyone know what could cause this? In my Debugging settings I have unchecked the: "Suppress JIT opimization on module load" -setting, as suggested elsewhere, but that doesn't help.
Is there something that I don't understant of making an UWP-app, where you can click buttons at the top, and a page would change below them. Here's the XAML behind this:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="2*"/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="3" x:Name="stackPanel_up" Orientation="Horizontal" HorizontalAlignment="Center"
VerticalAlignment="Center" Margin="10">
<Button x:Name="eka" Background="Aqua" Content="First" Width="200"
Height="50" FontSize="30" FontWeight="Bold" CornerRadius="10" Margin="5,0,5,0"
Click="eka_Click"/>
<Button x:Name="toka" Background="Aqua" Content="Second" Width="200" Height="50"
FontSize="30" FontWeight="Bold" CornerRadius="10" Margin="5,0,5,0"
Click="toka_Click"/>
<Button x:Name="kolmas" Background="Aqua" Content="Third" Width="200" Height="50"
FontSize="30" FontWeight="Bold" CornerRadius="10" Margin="5,0,5,0"
Click="kolmas_Click"/>
</StackPanel>
<Button Grid.Column="0" Grid.Row="0" x:Name="BackBtn" FontSize="50" Margin="40,0,0,0"
HorizontalAlignment="Left" Width="100" Height="100" CornerRadius="30"
Background="Transparent" Click="Back_Click" Style="{StaticResource NavigationBackButtonNormalStyle}" />
<Frame Grid.Row="1" Grid.Column="0" Grid.ColumnSpan="3" x:Name="ChangingArea" Margin="10" Background="AliceBlue"></Frame>
</Grid>
I'm working on a WPF application where I've made a ListView on UI which is two-way binding enabled. This WPF application is being developed for a windows 10 based smartphone. So whenever a user taps an item in the list whose data source is data-binded to back data collection, I've to do some operation for that item in code behind.
Now the problem is, I always receive a null object from the below function whenever the user taps on the item.
CartItem selectedItem = (CartItem)lv_CartItems.SelectedItem;
I only get a filled item object when the user actually selects an item by clicking on ListViewItem rather than tapping on it.
I want to get the selected item when the user taps on it. Is there any workaround available in WPF this problem? I've stuck here
My ListViewItem template looks like this.
<ListView Name="lv_CartItems" Loaded="lv_CartItems_Loaded"
HorizontalAlignment="Center" ScrollViewer.CanContentScroll="False"
ScrollViewer.VerticalScrollBarVisibility="Visible"
Width="250" Height="230" SelectionMode="Single"
>
<ListView.ItemTemplate>
<DataTemplate>
<Viewbox>
<Grid Width="230" Height="110" >
<Grid.ColumnDefinitions>
<ColumnDefinition/>
<ColumnDefinition Width=".1*" />
<ColumnDefinition />
<ColumnDefinition/>
<ColumnDefinition/>
<ColumnDefinition Width=".5*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="2*" />
<RowDefinition/>
<RowDefinition/>
</Grid.RowDefinitions>
<Border BorderBrush="LightGray" BorderThickness="1"
Grid.Row="0" Grid.Column="0"
Grid.ColumnSpan="6" Grid.RowSpan="3" >
</Border>
<Viewbox Grid.Row="0" >
<Image Name="img_ItemImage"
Source="{Binding Image, Mode=TwoWay }"
Width="20" Height=" 25" />
</Viewbox>
<Viewbox Grid.Column="2" Grid.ColumnSpan="3" VerticalAlignment="Top" >
<TextBlock Name="lbl_ItemName" TextWrapping="Wrap" Width="180" Foreground="Gray"
Text="{Binding Name , Mode=TwoWay }" >
</TextBlock>
</Viewbox>
<Viewbox Grid.Row="1" Margin="10,0" VerticalAlignment="Top" >
<TextBlock Foreground="Gray" >Qty:</TextBlock>
</Viewbox>
<Viewbox Grid.Row="2" Margin="0,0" VerticalAlignment="Top" >
<StackPanel Orientation="Horizontal" >
<Button Name="btn_Minus" FontWeight="ExtraBold" Tag="{Binding SKU_No,Mode=TwoWay}" Padding="0" Width="12"
Resources="{StaticResource cartitembutton}" Click="btn_Minus_Click" >
<Image Source="/Resources\Icons\minus.png" ></Image>
</Button>
<Border BorderThickness="1" Margin="2,0" Width="13" CornerRadius="2" BorderBrush="LightGray" >
<TextBlock Name="lbl_Quantity" FontWeight="Bold" Foreground="Gray"
HorizontalAlignment="Center" VerticalAlignment="Center"
Text="{Binding Quantity , Mode=TwoWay }" >
</TextBlock>
</Border>
<Button Name="btn_Increment" FontWeight="ExtraBold" Width="12"
Resources="{StaticResource cartitembutton}" Tag="{Binding SKU_No,Mode=TwoWay}"
Padding="0"
Click="btn_Increment_Click">
<Image Source="/Resources\Icons\union_10.png" ></Image>
</Button>
</StackPanel>
</Viewbox>
<Viewbox Grid.Row="1" Grid.Column="2" Margin="5,0"
HorizontalAlignment="Left" Grid.ColumnSpan="3" >
<TextBlock Name="lbl_Price" FontWeight="DemiBold"
Text="{Binding Price , Mode=TwoWay}" ></TextBlock>
</Viewbox>
<Viewbox Grid.Row="2" Grid.Column="2" Grid.ColumnSpan="3"
VerticalAlignment="Top" Margin="0,0" >
<TextBlock Name="lbl_Appearence"
Text="{Binding Appearance , Mode=TwoWay }"
TextWrapping="Wrap" Foreground="Gray" Width="210" >
</TextBlock>
</Viewbox>
<Viewbox Grid.Column="5" HorizontalAlignment="Center" VerticalAlignment="Top" Margin="2,2"
>
<Button Name="btn_DeleteItem"
Click="btn_DeleteItem_Click"
Resources="{StaticResource cartitembutton}" >
<Image Source="/Resources/Icons/delete.png" ></Image>
</Button>
</Viewbox>
</Grid>
</Viewbox>
</DataTemplate>
</ListView.ItemTemplate>
</ListView>
This is how a listVeiw looks like.
You don't actually want the selected item, you want to know which item contained the button that was clicked- whether that item is selected or not.
You can do this with events, but the more "correct" way to do it in WPF is with commands.
Commands are a pattern which separate the logic of an action (e.g. deleting an item) from the visual component that triggers the action (e.g. the button the user clicks). A command includes a parameter, which you can use to specify which item the command is being executed on. There are a couple different types on commands in WPF, but I'll be explaining using RoutedCommand.
In your case you'd first declare your command(s) in your Window:
public static readonly RoutedCommand DeleteItemCommand =
new RoutedCommand("DeleteItem", typeof(MainWindow));
private void OnCanExecuteDeleteItem(object sender , CanExecuteRoutedEventArgs e)
{
e.CanExecute = e.Parameter != null;
}
private void OnExecuteDeleteItem(object sender, ExecutedRoutedEventArgs e)
{
SomeType item = (SomeType)e.Parameter;
//Actually delete the item
}
And you'd add a CommandBinding to your Window which links the command to the methods which handle it:
<Window.CommandBindings>
<CommandBinding Command="local:MainWindow.DeleteItemCommand" CanExecute="OnCanExecuteDeleteItem" Executed="OnExecuteDeleteItem"/>
</Window.CommandBindings>
And finally, to link your delete Button to the command:
<Button Name="btn_DeleteItem" Resources="{StaticResource cartitembutton}" Command="local:MainWindow.DeleteItemCommand" CommandParameter="{Binding}">
<Image Source="/Resources/Icons/delete.png"/>
</Button>
CommandParameter="{Binding}" works because your Button is inside a DataTemplate, so its DataContext will be the item that is being displayed. This lets you check e.Parameter in your routed event methods to see which item is being interacted with.
I got my DataTemplate for items and within this DataTemplate I have such code:
<Button x:Name="DoneButton"
Style="{StaticResource ButtonStyle1}"
BorderThickness="1"
Margin="0,0,20,0"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Grid.Column="2"
Grid.Row="1"
Width="50"
Height="50"
>
<Image Source="Images/WPIcons/checked.png" Width="30" Height="30" Margin="-10,0,-10,0" />
<Button.Flyout>
<Flyout x:Name="myFly">
<Grid Margin="10">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBlock Grid.Row="0" x:Uid="myNote" Text="Note: " Style="{StaticResource myText}" />
<TextBox Grid.Row="1" TextWrapping="Wrap" AcceptsReturn="True" Height="40" x:Name="note" Text="{Binding RecentNote, Mode=TwoWay}" Style="{StaticResource TextBoxStyle1}"/>
<Button x:Name="CompletedButton"
Command="{Binding CompletedCommand}"
CommandParameter="{Binding}"
Style="{StaticResource ButtonStyle1}"
BorderThickness="1"
HorizontalAlignment="Left"
VerticalAlignment="Center"
Grid.Row="2"
Click="CompletedButton_Click"
Content="Done"
MinWidth="80"
Height="40"
/>
</Grid>
</Flyout>
</Button.Flyout>
</Button>
After the flyout for the item has been called and user put his data in it I want to hide this flyout as soon as user hits the "Done" button (x:Name="CompletedButton").
I tried to do that in code behind like:
private void CompletedButton_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
Grid grid = (Grid)VisualTreeHelper.GetParent(button);
Flyout fly = (Flyout)VisualTreeHelper.GetParent(grid);
fly.Hide();
}
But I get cast exception with that I can't cast ContentPresenter to Flyout so I guess it's not the way I look for.
How I can hide this flyout?
I resolved it with creating global DependencyObject on the page. So when you click the button it keeps it and I can call its flyout to hide() from button within this flyout. A bit ugly but works like a charm.
I have the following XAML code..
<phone:PhoneApplicationPage.Resources>
<DataTemplate x:Key="DataTemplate1" >
<Border BorderBrush="LightGray" BorderThickness="1" Height="150" Width="500" >
<Grid Width="500" Height="150" Background="White" >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.5*"/>
<ColumnDefinition Width="2.5*"/>
<ColumnDefinition Width="1*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Image Grid.Column="0" Height="Auto" Width="Auto" Source="/Images/notav.jpg" Margin="0,5,4,4" HorizontalAlignment="Left" />
<TextBlock Text="{Binding PRICE}" TextWrapping="Wrap" Grid.Column="1" Width="350" Foreground="Black" Height="60" Margin="30,85,20,-10"/>
<TextBlock Text="{Binding ITMNAME }" FontSize="22" TextWrapping="Wrap" Grid.Column="1" Name="txtITMNAME" Foreground="DarkBlue" Width="500" Height="130" Margin="30,40,20,-10"/>
<c4f:RoundButton Grid.Column="2" Name="btntick" Click="btntick_Click" Grid.Row="0" FontSize="25" HorizontalAlignment="Right" Background="LightGray" Foreground="DarkGray" Margin="10,20,45,10" />
</Grid>
</Border>
</DataTemplate>
<ListBox Height="Auto" Name="lstbxmanual" ItemTemplate="{StaticResource DataTemplate1 }" Width="475" Margin="4,148,0,5" Background="White" HorizontalAlignment="Left" Grid.RowSpan="2">
</ListBox>
I have to access round button at code behind ,to change its background property...
private void btntick_Click(object sender, RoutedEventArgs e)
{
btntick. //not able to access...
}
I have gone through following stackoverflow questions..
Access DataTemplate controls in code behind
MSDN link
it seems to be not relevant to my requirement..
please help me in this regard...
Solution 1: Use x:Name instead of Name.
Solution 2: Here is the an alternate way too.
You can cast the event sender object:
private void btntick_Click(object sender, RoutedEventArgs e)
{
RoundButton rdbtn = sender as RoundButton;
//rdbtn.BackColor
}
please try, x:Name in place of Name it will be accessible from your code behind file.
<c4f:RoundButton Grid.Column="2" x:Name="btntick" Click="btntick_Click" Grid.Row="0" FontSize="25" HorizontalAlignment="Right" Background="LightGray" Foreground="DarkGray" Margin="10,20,45,10" />
private void btntick_Click(object sender, RoutedEventArgs e)
{
btntick.Foreground = Brushes.Blue;
}
Good Luck.
Wasn't sure how to title this, but basically I have created a cropping function for cropping images and it looks a bit like this:
At the moment, the user can move this box (which is actually just a border with several child borders) and draw new ones of any size. What it can't do, is allow the user to resize it after already drawn. It has to be able to resize in each direction you see a small square. For this, the only thing I can think of to do is write a MouseUp, MouseDown, and MouseMove method for each one.
My first question is, can this be simplified so that we can eliminate having to have 24 events for achieving this?
My second question is, if NOT, how would I go about actually resizing it?
My current algorithm would mean resizing the parent border and changing the (x,y) coordinates of this on the canvas, but I would also like to allow the possibility of resizing past the top point.
For example, if the user is resizing up using the bottom-most square, the border would eventually have a zero height, but then continue going in that direction. So essentially, the border would have a fixed top position until the mouse extended beyond that point, then it would have a fixed bottom position as the height increases upward. I tested this with just one square and now it's starting to seem more complicated than it is worth completing.
This is a sample of my current algorithm:
private void southCropBorder_MouseDown(object sender, MouseButtonEventArgs e)
{
this.southCropBorder.CaptureMouse();
}
private void southCropBorder_MouseUp(object sender, MouseButtonEventArgs e)
{
this.southCropBorder.ReleaseMouseCapture();
}
private void southCropBorder_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton != MouseButtonState.Pressed) { return; }
double Y_1 = Canvas.GetTop(this.croppingBorder);
double Y_2 = e.GetPosition(this.canvas1).Y;
double Y_3 = Y_2 - Y_1;
if (Y_3 > 0)
{
this.croppingBorder.Height = Y_2 - Y_1;
}
else
{
if (Y_3 != 0)
{
Canvas.SetBottom(this.croppingBorder, Y_1);
this.croppingBorder.Height = Y_3 * -1;
}
}
}
And then the XAML:
<Border x:Name="croppingBorder" Cursor="SizeAll" Panel.ZIndex="1000" Visibility="Hidden" Background="LightGray" Width="0" Height="0" BorderThickness="1" BorderBrush="Black" Opacity="0.6">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="34*"/>
<ColumnDefinition Width="33*"/>
<ColumnDefinition Width="33*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="34*"/>
<RowDefinition Height="33*"/>
<RowDefinition Height="33*"/>
</Grid.RowDefinitions>
<Border x:Name="northWestCropBorder" Background="Gray" Panel.ZIndex="1" Cursor="SizeNWSE" Grid.Column="0" Grid.Row="0" HorizontalAlignment="Left" VerticalAlignment="Top" Width="10" Height="10" BorderBrush="White" BorderThickness="1" Margin="-5,-5,0,0" MouseUp="northWestCropBorder_MouseUp" MouseDown="northWestCropBorder_MouseDown"/>
<Border x:Name="northCropBorder" Background="Gray" Panel.ZIndex="1" Cursor="SizeNS" Grid.Column="1" Grid.Row="0" HorizontalAlignment="Center" VerticalAlignment="Top" Width="10" Height="10" BorderBrush="White" BorderThickness="1" Margin="0,-5,-5,0" MouseUp="northCropBorder_MouseUp" MouseDown="northCropBorder_MouseDown"/>
<Border x:Name="northEastCropBorder" Background="Gray" Panel.ZIndex="1" Cursor="SizeNESW" Grid.Column="2" Grid.Row="0" HorizontalAlignment="Right" VerticalAlignment="Top" Width="10" Height="10" BorderBrush="White" BorderThickness="1" Margin="0,-5,-5,0" MouseUp="northEastCropBorder_MouseUp" MouseDown="northEastCropBorder_MouseDown"/>
<Border x:Name="westCropBorder" Background="Gray" Panel.ZIndex="1" Cursor="SizeWE" Grid.Column="0" Grid.Row="1" HorizontalAlignment="Left" VerticalAlignment="Center" Width="10" Height="10" BorderBrush="White" BorderThickness="1" Margin="-5,0,0,0" MouseUp="westCropBorder_MouseUp" MouseDown="westCropBorder_MouseDown"/>
<Ellipse Fill="Gray" Panel.ZIndex="1" Cursor="Arrow" Grid.Column="1" Grid.Row="1" HorizontalAlignment="Center" VerticalAlignment="Center" Width="10" Height="10" Stroke="White" StrokeThickness="1" Margin="0,0,-5,0"/>
<Border x:Name="eastCropBorder" Background="Gray" Panel.ZIndex="1" Cursor="SizeWE" Grid.Column="2" Grid.Row="1" HorizontalAlignment="Right" VerticalAlignment="Center" Width="10" Height="10" BorderBrush="White" BorderThickness="1" Margin="0,0,-5,0" MouseUp="eastCropBorder_MouseUp" MouseDown="eastCropBorder_MouseDown"/>
<Border x:Name="southWestCropBorder" Background="Gray" Panel.ZIndex="1" Cursor="SizeNESW" Grid.Column="0" Grid.Row="2" HorizontalAlignment="Left" VerticalAlignment="Bottom" Width="10" Height="10" BorderBrush="White" BorderThickness="1" Margin="0,0,-5,-5" MouseUp="southWestCropBorder_MouseUp" MouseDown="southWestCropBorder_MouseDown"/>
<Border x:Name="southCropBorder" Background="Gray" Panel.ZIndex="1" Cursor="SizeNS" Grid.Column="1" Grid.Row="2" HorizontalAlignment="Center" VerticalAlignment="Bottom" Width="10" Height="10" BorderBrush="White" BorderThickness="1" Margin="0,0,-5,-5" MouseUp="southCropBorder_MouseUp" MouseDown="southCropBorder_MouseDown" MouseMove="southCropBorder_MouseMove"/>
<Border x:Name="southEastCropBorder" Background="Gray" Panel.ZIndex="1" Cursor="SizeNWSE" Grid.Column="2" Grid.Row="2" HorizontalAlignment="Right" VerticalAlignment="Bottom" Width="10" Height="10" BorderBrush="White" BorderThickness="1" Margin="0,0,-5,-5" MouseUp="southEastCropBorder_MouseUp" MouseDown="southEastCropBorder_MouseDown"/>
<Image x:Name="croppingSelectionImage" Grid.ColumnSpan="3" Grid.RowSpan="3" Stretch="Fill" MouseDown="croppingSelectionImage_MouseDown" MouseMove="croppingSelectionImage_MouseMove"/>
</Grid>
</Border>
At this point, resizing is all fine and dandy until you start trying to extend beyond the initial top position.
Any thoughts?
UPDATE
Ok, so I came across this, which really makes more sense. Still pondering how it can be made to move in opposite side directions, as well. I have provided an example image in photoshop to exemplify what I'm trying to acheive:
Note, how we start at the bottom and move our way up to the top (which is something photoshop can actually do). Will start here and update when I find a fix...