I'm making a Windows Desktop Application that have drag and drop functionality.
I'm using Polygon (And Images later) Shapes for drag and drop. The drag and drop functionality works fine but I want that if user drag any shape from the panel and when he drag other shape then the second shape automatically fix with first shape.
You'll understand it by take a look at below screenshots.
It is the Screen Shot of what happens when I drag Shapes
When user drop the polygon near the other polygon it will automatically adjust itself, if the same polygon drop in other area of canvas than a error will show to the user.
Here is my XAML Code
<Window x:Class="Images.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:Images"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<DockPanel
VerticalAlignment="Stretch"
Height="Auto">
<DockPanel
HorizontalAlignment="Stretch"
VerticalAlignment="Stretch"
Height="Auto"
MinWidth="400"
Margin="10">
<GroupBox
DockPanel.Dock="Left"
Width="350"
Background="Aqua"
VerticalAlignment="Stretch"
VerticalContentAlignment="Stretch"
Height="Auto">
<WrapPanel Margin="0,10,0,0" VerticalAlignment="Top">
<Button Name="control" Content="Control" Height="30" Background="BlueViolet" Margin="5" Width="100"/>
<Button Name="motion" Content="Motion" Width="100" Margin="5" Background="Green" Height="30"/>
<Button Name="variable" Content="Variable" Width="100" Margin="5" Background="SeaGreen" Height="30"/>
<Button Name="sensor" Content="Sensor" Width="100" Margin="5" Background="OrangeRed" Height="30"/>
<Button Name="lcd" Content="LCD" Width="100" Margin="5" Height="30" Background="PaleVioletRed"/>
<Button Name="function" Content="Function" Width="100" Margin="5" Height="30" Background="Salmon"/>
<StackPanel Name="heaading" Width="350">
<TextBlock Name="controlName" TextAlignment="Center" Text="Controls"/>
</StackPanel>
<StackPanel Name="userControls" Orientation="Vertical">
<!-- Users Controls Items Goes Here -->
<Polygon Name="startProgram" Points="80,10, 80, 80, 135,80, 135, 45, 205, 45, 205, 80, 260, 80, 260,10" Fill="Chocolate" Stroke="Black" StrokeThickness="2" MouseLeftButtonDown="shape_MouseLeftButtonDown" />
<Polygon Name="endProgram" Fill="BlueViolet" Points="80,40, 80,80, 260,80, 260,40, 200,40, 200,10, 140,10,140,40" Stroke="Black" StrokeThickness="2" MouseLeftButtonDown="shape_MouseLeftButtonDown" />
</StackPanel>
</WrapPanel>
</GroupBox>
<!-- Change this to Canvas for work later -->
<Canvas x:Name="dropArea" DockPanel.Dock="Right" Margin="10" Background="#FF9760BF" Width="Auto" HorizontalAlignment="Stretch" AllowDrop="True" Drop="dropArea_Drop">
</Canvas>
</DockPanel>
</DockPanel>
</Window>
Here is my CS code
namespace Images
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void dropArea_Drop(object sender, DragEventArgs e)
{
var shape = e.Data.GetData(typeof(Polygon)) as Polygon;
Console.WriteLine("Polygon Name : " + shape.Name);
Polygon myPolygon = new Polygon();
myPolygon.Stroke = shape.Stroke;
myPolygon.Fill = shape.Fill;
myPolygon.StrokeThickness = 2;
Canvas.SetTop(myPolygon, e.GetPosition(dropArea).Y);
myPolygon.Points = shape.Points;
dropArea.Children.Add(myPolygon);
myPolygon.MouseRightButtonDown += new MouseButtonEventHandler(dragged_ShapeMouseDown);
}
private void dragged_ShapeMouseDown(object sender, MouseButtonEventArgs e)
{
//Show Options to Delete or set Value to current Polygon
}
private void shape_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
Polygon shape = e.Source as Polygon;
DragDrop.DoDragDrop(shape, shape, DragDropEffects.Copy);
}
}
}
Problem
I'm using Canvas.setTop because without setting it my polygon show over the first.
Here I'm setting the polygon that fix with its above polygon but it can be left or right also as shown in below screenshot.
SOLUTION
For Deleting shape
myPolygon.MouseLeftButtonUp += new MouseButtonEventHandler(dragged_ShapeMouseDown);
private void dragged_ShapeMouseDown(object sender, MouseButtonEventArgs e)
{
if (dropArea.Children.Count > 0)
dropArea.Children.Remove(sender as Polygon);
}
Sacha Barber has got very nice article that describe exactly what you are trying to do i think...4 steps articles up to MVVM ! have a look these step1 and
step2, step3, step4 - I also used it in my own project ArchX
well, i think everything is there in my code : during onmove test the result and change the cursor. ondragend : use a HitHelper to determine where you release the mouse and return the shape his tested - then adjust the shape of the polygon regarding the hit result : below sample code - GuideLineManager
public Cursor HitTestGuide(Point p, RulerOrientation mode)
{
if (_Guides.Exists(g => (int)g.Info.Orientation == (int)mode && g.HitTest(p)))
{
return _Guides.First(g => (int)g.Info.Orientation == (int)mode && g.HitTest(p)).Cursor;
}
return Cursors.Arrow;
}
and the onDragEnd, call to get the hit tested object
public Guideline GetSnapGuide(Point hitPoint)
{
foreach (Guideline gl in Guides)
{
if (!gl.IsDisplayed) continue;
if (gl.Info.IsSnap && !gl.Info.IsMoving)
if (gl.IsOnGuide(hitPoint, _Container.dPicCapture))
{
return gl;
}
}
return null;
}
Related
I want my Popup to always appear in a specific corner (lower right corner e.g.) no matter the size and the resolution of my View.
I tried using HorizontalAlignment and VerticalAlignment but it's not really working.
Here's my code :
<Grid x:Name="Output" HorizontalAlignment="Right" VerticalAlignment="Bottom" Grid.Row="1">
<Popup x:Name="StandardPopup">
<Border BorderBrush="{StaticResource ApplicationForegroundThemeBrush}"
Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
BorderThickness="2" Width="500" Height="500">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<WebView x:Name="WebView1" Source="https://www.bing.com/" Width="490" Height="490" HorizontalAlignment="Center"/>
</StackPanel>
</Border>
</Popup>
</Grid>
You can create a UserControl to help you achieve this.
Create a new UserControl called TestPopup
<UserControl
...
>
<Grid>
<Grid HorizontalAlignment="Right" VerticalAlignment="Bottom">
<Border BorderBrush="{StaticResource ApplicationForegroundThemeBrush}"
Background="{StaticResource ApplicationPageBackgroundThemeBrush}"
BorderThickness="2" Width="500" Height="500">
<StackPanel HorizontalAlignment="Center" VerticalAlignment="Center">
<WebView x:Name="WebView1" Source="https://www.bing.com/" Width="490" Height="490" HorizontalAlignment="Center"/>
</StackPanel>
</Border>
</Grid>
</Grid>
</UserControl>
The code-behind:
public sealed partial class TestPopup : UserControl
{
private Popup _popup = null;
public TestPopup()
{
this.InitializeComponent();
// If you need to top placement, please comment out the Width/Height statement below
this.Width = Window.Current.Bounds.Width;
this.Height = Window.Current.Bounds.Height;
//Assign the current control to the Child property of the popup. The Child property is what the popup needs to display.
_popup = new Popup();
_popup.Child = this;
}
public void ShowPopup()
{
_popup.IsOpen = true;
}
public void HidePopup()
{
_popup.IsOpen = false;
}
}
Use C# code references where needed
public sealed partial class MainPage : Page
{
private TestPopup _popup = new TestPopup();
public MainPage()
{
this.InitializeComponent();
_popup.ShowPopup();
}
}
To ensure that it is in the lower right corner at any width, you can listen to the page's SizeChanged event.
private void Page_SizeChanged(object sender, SizeChangedEventArgs e)
{
_popup.Width = Window.Current.Bounds.Width;
_popup.Height = Window.Current.Bounds.Height;
// If you need to use the Width/Height of the page
// _popup.Width = e.NewSize.Width;
// _popup.Height = e.NewSize.Height;
}
Best regards.
Sadly Popup does not support Alignments you have to use the Offset Values
NOTE: Don't forget that you can use Bindings for Offsets and so get your wanted behavior with some Converter magic.
<Popup HorizontalOffset="20"
VerticalOffset="10">
<!--Content-->
</Popup>
I'm trying to implement some WPF drawing sample to understand how it works. I can solve such task with C++ very quickly but I want to understand WPF means.
During the implementation of a task I faced with some strange problem: coordinates shift of mouse cursor responsible to pixels I can see on canvas.
First of all, my task is: load some picture from file; show it on Image component; allow to draw over image with mouse (like pencil tool); save changes to new file. Task is easy to implement.
Here is my code:
XAML:
<Window x:Class="MyPaint.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:MyPaint"
xmlns:xctk="http://schemas.xceed.com/wpf/xaml/toolkit"
Background="#FF000000"
mc:Ignorable="d"
Title="Strange Paint" Height="503.542" Width="766.281" Icon="icons/paint.png">
<Grid >
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="20"/>
<RowDefinition Height="*"/>
</Grid.RowDefinitions>
<Grid Grid.Column="0" Grid.Row="1" Width="Auto">
<StackPanel HorizontalAlignment="Left" Width="Auto" Background="{x:Null}">
<Button x:Name="arrowButton" Width="25" Height="25" HorizontalAlignment="Left" Click="ArrowButton_Click">
<Image Source="icons/arrow.png"/>
</Button>
<Button x:Name="selectorButton" Width="25" Height="25" Click="SelectorButton_Click" HorizontalAlignment="Left">
<Image Source="icons/select_selection_tool-128.png"/>
</Button>
<Button x:Name="clearButton" Width="25" Height="25" Click="ClearButton_Click" HorizontalAlignment="Left">
<Image Source="icons/clear.png"/>
</Button>
<Button x:Name="pencilButton" Width="25" Height="25" Click="PencilButton_Click" HorizontalAlignment="Left">
<Image Source="icons/pencil.png"/>
</Button>
<Button x:Name="fillButton" Width="25" Height="25" Click="FillButton_Click" HorizontalAlignment="Left">
<Image Source="icons/fill.png"/>
</Button>
<xctk:ColorPicker Width="50" Name="ClrPcker_Foreground" SelectedColorChanged="ClrPcker_Foreground_SelectedColorChanged">
</xctk:ColorPicker>
</StackPanel>
</Grid>
<Grid x:Name="drawingCanvas" Grid.Column="1" Grid.Row="1" MouseMove="paintImageCanvas_MouseMove" MouseLeave="PaintImageCanvas_MouseLeave" MouseLeftButtonUp="PaintImageCanvas_MouseLeftButtonUp">
<ScrollViewer Grid.Column="1" HorizontalScrollBarVisibility="Auto" VerticalScrollBarVisibility="Auto">
<Canvas x:Name="scrCanvas" Width="{Binding ActualWidth, ElementName=paintImageCanvas}" Height="{Binding ActualHeight, ElementName=paintImageCanvas}" >
<Image x:Name="paintImageCanvas" HorizontalAlignment="Left" VerticalAlignment="Top" Stretch="UniformToFill" MouseDown="paintImageCanvas_MouseDown" MouseMove="paintImageCanvas_MouseMove">
</Image>
<Rectangle x:Name="Rect" Stroke="DarkOrange" Visibility="Collapsed" Fill="#77EEEEEE"></Rectangle>
</Canvas>
</ScrollViewer>
</Grid>
<StackPanel Grid.Row="0">
<Menu IsMainMenu="True" DockPanel.Dock="Top" Background="#FF000000">
<MenuItem Header="_File" Foreground="White" Background="#FF000000">
<MenuItem x:Name="newMenuItem" Header="_New" Background="#FF000000" Click="NewMenuItem_Click"/>
<MenuItem x:Name="openMenuItem" Header="_Open" Click="openMenuItem_Click" Background="#FF000000"/>
<MenuItem Header="_Close" Background="#FF000000"/>
<MenuItem Header="_Save" Background="#FF000000" Click="MenuItem_Click"/>
<MenuItem x:Name="exitMenuItem" Header="_Exit" Click="exitMenuItem_Click" Background="#FF000000"/>
</MenuItem>
</Menu>
<StackPanel></StackPanel>
</StackPanel>
</Grid>
Implementation of window class:
Class members:
Point currentPoint = new Point();
ToolBoxTypes currentSelectedTool = ToolBoxTypes.Unknown;
Color foregroundColor = Brushes.Black.Color;
WriteableBitmap imageWriteableBitmap;
Constructor and initialization (init white canvas 1024x768):
public MainWindow()
{
InitializeComponent();
ClrPcker_Foreground.SelectedColor = foregroundColor;
imageWriteableBitmap = BitmapFactory.New(1024, 768);
paintImageCanvas.Source = imageWriteableBitmap;
imageWriteableBitmap.Clear(Colors.White);
int i = 0;
}
Mouse down event (here I get the first point):
private void paintImageCanvas_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ButtonState == MouseButtonState.Pressed)
{
currentPoint = e.GetPosition(paintImageCanvas);
}
if (currentSelectedTool == ToolBoxTypes.PencilTool)
{
}
}
Mouse move event (draw on canvas if pressed):
private void paintImageCanvas_MouseMove(object sender, MouseEventArgs e)
{
if (e.LeftButton == MouseButtonState.Pressed)
{
if(currentSelectedTool == ToolBoxTypes.PencilTool)
{
int x1 = Convert.ToInt32(currentPoint.X);
int y1 = Convert.ToInt32(currentPoint.Y);
int x2 = Convert.ToInt32(e.GetPosition(paintImageCanvas).X);
int y2 = Convert.ToInt32(e.GetPosition(paintImageCanvas).Y);
Console.WriteLine("Mouse X: " + x2 + " Mouse Y: " + y2);
imageWriteableBitmap.DrawLine( x1, y1, x2, y2, foregroundColor );
currentPoint = e.GetPosition(paintImageCanvas);
}
}
}
Ok. That's easy code.
And now, two usecases:
On start and init I can see white canvas and can draw with mouse without any problem (cursor follows pixels):
usecase 1
I loaded picture (size is 700x600) and got a problem, cursor has different place (can see a shift):
usecase 2
I think that problem is that canvas (Image) has different side than actual picture's side. I'm not sure.
Could you help me please to understand what is wrong and how to fix that?
Thanks.
Thanks to Dmitry (see comments on my question) the reason of the problem has been found: DPI of source picture.
I changed my code of picture loading and it works fine:
private void openMenuItem_Click(object sender, RoutedEventArgs e)
{
OpenFileDialog openFileDialog = new OpenFileDialog();
openFileDialog.Filter = "JPEG files (*.jpg)|*.jpg|PNG files (*.png)|*.png";
if (openFileDialog.ShowDialog() == true)
{
BitmapImage image = new BitmapImage(new Uri(openFileDialog.FileName));
imageWriteableBitmap = new WriteableBitmap(image);
double dpi = 96;
int width = imageWriteableBitmap.PixelWidth;
int height = imageWriteableBitmap.PixelHeight;
int stride = width * 4;
byte[] pixelData = new byte[stride * height];
imageWriteableBitmap.CopyPixels(pixelData, stride, 0);
BitmapSource bmpSource = BitmapSource.Create(width, height, dpi, dpi, PixelFormats.Bgra32, null, pixelData, stride);
imageWriteableBitmap = new WriteableBitmap(
bmpSource.PixelWidth,
bmpSource.PixelHeight,
bmpSource.DpiX, bmpSource.DpiY,
bmpSource.Format, null);
imageWriteableBitmap.WritePixels(
new Int32Rect(0, 0, bmpSource.PixelWidth, bmpSource.PixelHeight), pixelData, stride, 0);
paintImageCanvas.Source = imageWriteableBitmap;
}
}
I'm trying to get the positions of controls (buttons) but it keeps returning {0;0}. I'm sure there's an explanation for this, but I can't figure out why this happens.
I want the position of the control, relative to the window or a certain container. My buttons are arranged in another grid. Taking the margins of these buttons would just give 0,0 since they're all inside grid cells.
What I tried:
- var point = btnTest.TransformToAncestor(mainGrid).Transform(new Point());
- UIElement container = VisualTreeHelper.GetParent(btnTest) as UIElement;
Point relativeLocation = btnTest.TranslatePoint(new Point(0, 0), mainGrid);
I tried this with a grid as a parent and with a canvas. Everything I try gives me {0,0}. When I change the new Point parameters, the position does change. It stays the same as the parameters.
Small part of my XAML:
<Grid x:Name="mainGrid">
<Grid Name="buttonGrid" Margin="105,64,98.4,97.8">
<Grid.RowDefinitions>
<RowDefinition Height="25"/>
<RowDefinition Height="25"/>
<RowDefinition Height="25"/>
</Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="50"/>
<ColumnDefinition Width="50"/>
</Grid.ColumnDefinitions>
<Button x:Name="btnTest" Grid.Row="0" Grid.Column="0" Content="Button" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" Width="26" Height="29"/>
<Button x:Name="btnTest2" Grid.Row="1" Grid.Column="1" Content="Button" HorizontalAlignment="Left" Margin="0,0,0,0" VerticalAlignment="Top" Width="26" Height="29"/>
</Grid>
</Grid>
Your code works perfectly fine, it is the timing that is the issue. The UI elements must be drawn before the position can be retrieved.
The code sample below shows the point extraction running in the constructor with the result 0,0 and then running in the loaded event which returns the desired result 84,78.
<Window x:Class="WpfApp7.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="450" Width="800" Loaded="Window_Loaded">
<Grid x:Name="mainGrid">
<Button x:Name="btnTest" Content="TileButton" HorizontalAlignment="Left" Margin="84,78,0,0" VerticalAlignment="Top" Width="109" Height="103"/>
</Grid>
public MainWindow()
{
InitializeComponent();
GetPoint();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
GetPoint();
}
private void GetPoint()
{
var point = btnTest.TransformToAncestor(mainGrid).Transform(new Point());
UIElement container = VisualTreeHelper.GetParent(btnTest) as UIElement;
Point relativeLocation = btnTest.TranslatePoint(new Point(0, 0), mainGrid);
MessageBox.Show($"X = {relativeLocation.X} Y = {relativeLocation.Y}");
}
I'm trying to create an expandable/collapsible menu for a personal project of mine. I have everything almost where I want it (in terms of it being behaving as expected anyway). When I collapse my menu, I want the buttons to rotate to a vertical position and not resize (Or at least resize to something that still fits the text). At the moment, the buttons rotate, then shrink vertically (what was/is the width) along with the parent control, which cuts off much of the contents. I can see why this would happen, but I can't think of a way around it that seems right to me.
Here is the behavior I'm seeing:
Before: After:
As you can see, the buttons are shrinking along their now-vertical width (to what I assume would be the width of the enclosing StackPanel).
Here is the code I am using:
ExpaningMenu.xaml
<UserControl x:Class="Budgety.Controls.ExpandingMenu"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Budgety.Controls"
mc:Ignorable="d"
Name="MainExpandingMenu"
MinWidth="32"
d:DesignHeight="300" d:DesignWidth="100">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Name="MenuPanel" Width="100" HorizontalAlignment="Left" Background="{DynamicResource BackColor}" Grid.Row="1">
<!--Contents will go here-->
</StackPanel>
<Button Name="StateToggle" Width="100" Height="32" FontSize="18" VerticalAlignment="Center" HorizontalAlignment="Stretch" Panel.ZIndex="1" Background="{DynamicResource BackColor}" BorderThickness="0" Click="Button_Click" Content="«"></Button>
</Grid>
</UserControl>
ExpandingMenu.xaml.cs
public partial class ExpandingMenu : UserControl
{
public ExpandingMenu()
{
InitializeComponent();
//For testing purposes.
MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 1"));
MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 2"));
MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 3"));
MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 4"));
MenuPanel.Children.Add(new ExpandingMenuButton("TEST ITEM 5xxx"));
foreach (UIElement element in MenuPanel.Children)
{
(element as ExpandingMenuButton).HorizontalAlignment = HorizontalAlignment.Left;
}
}
#region Events
private void Button_Click(object sender, RoutedEventArgs e)
{
if (MenuPanel.Width == 100) //Need to collapse
{
StateToggle.Width = MenuPanel.Width = 32;
(sender as Button).Content = "\u00BB";
//Flip all children of this control (so far, assuming only ExpandingMenuButtons)
foreach (UIElement element in MenuPanel.Children)
{
(element as ExpandingMenuButton).LayoutTransform = new RotateTransform(-90);
//This works to resize to 100 tall (not ideal...)
//(element as ExpandingMenuButton).Width = 100;
//This does not seem to size to auto, which SHOULD make each button as long as the text requires... (this behavior is far less than ideal...)
//(element as ExpandingMenuButton).Width = Double.NaN;
}
}
else //Need to expand
{
StateToggle.Width = MenuPanel.Width = 100;
(sender as Button).Content = "\u00AB";
//Flip all children of this control (so far, assuming only ExpandingMenuButtons)
foreach (UIElement element in MenuPanel.Children)
{
(element as ExpandingMenuButton).LayoutTransform = new RotateTransform(0);
}
}
}
#endregion
}
ExpandingMenuButton.xaml
<UserControl x:Class="Budgety.Controls.ExpandingMenuButton"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="clr-namespace:Budgety.Controls"
mc:Ignorable="d"
d:DesignHeight="30" d:DesignWidth="100"
Height="30"
Name="ButtonControl">
<Grid Name="ButtonGrid" Height="30">
<ToggleButton Name="MenuButton" Background="Aqua" BorderThickness="1" Content="TEST"></ToggleButton>
</Grid>
</UserControl>
ExpandingMenuButton.xaml.cs
public partial class ExpandingMenuButton : UserControl
{
//Will definitely want custom functionalty here. TBD. Nothing special so far.
#region Constructors
public ExpandingMenuButton()
{
InitializeComponent();
}
public ExpandingMenuButton(string sText)
{
InitializeComponent();
MenuButton.Content = sText;
}
#endregion
}
If you'd like to test the code out, it should work placed in a normal grid as I have (The above mentioned UserControls I've made are in a Controls folder within the project):
<Window
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:Budgety"
xmlns:Controls="clr-namespace:Budgety.Controls" x:Class="Budgety.MainTest"
mc:Ignorable="d"
Title="MainTest" Height="600" Width="800">
<Grid>
<Controls:ExpandingMenu x:Name="ExpandingMenu" HorizontalAlignment="Left"/>
</Grid>
</Window>
After all is said and done, here is the behavior/look I am after (notice buttons are not shortened)
The reason for the layout you're seeing is the fixed height constraint you placed in ExpandingMenuButton: Height="30" on both the UserControl and the Grid element. You can change it to MinHeight.
In addition, when you set the width of the MenuPanel, you're also containing the height of the buttons, because you apply a transform.
Here's one way to fix this:
private void Button_Click(object sender, RoutedEventArgs e)
{
if (StateToggle.IsChecked == true)
{
StateToggle.Content = "\u00BB";
foreach (FrameworkElement element in MenuPanel.Children)
element.LayoutTransform = new RotateTransform(-90);
}
else
{
StateToggle.Content = "\u00AB";
foreach (FrameworkElement element in MenuPanel.Children)
element.LayoutTransform = null;
}
}
XAML:
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition />
</Grid.RowDefinitions>
<StackPanel Name="MenuPanel"
HorizontalAlignment="Left"
Background="{DynamicResource BackColor}"
Grid.Row="1">
<!--Contents will go here-->
</StackPanel>
<ToggleButton Name="StateToggle"
FontSize="18"
VerticalAlignment="Center"
HorizontalAlignment="Stretch"
Panel.ZIndex="1"
Background="{DynamicResource BackColor}"
BorderThickness="0"
Click="Button_Click"
Content="«" />
</Grid>
As a general rule, don't specify widths and heights in WPF - let the layout system do the measuring for you according to the content.
In my XAML i have a listbox and some textboxes in a grid and a reactangle in a canvas:
Title="MainWindow" Height="350" Width="500" WindowStartupLocation="CenterScreen">
<Grid>
<ListBox HorizontalAlignment="Left"
Margin="12,12,0,12"
Name="listBoxContainer"
Width="120">
<ListBoxItem Content="Item1" />
<ListBoxItem Content="Item2" />
<ListBoxItem Content="Item3" />
</ListBox>
<TextBox Height="23"
Margin="138,12,85,0"
Name="textBoxAddress"
VerticalAlignment="Top" />
<TextBox Margin="138,41,85,12"
Name="textBoxMsg" />
<Button Content="Button"
Name="buttonAnimation"
Width="75"
Margin="0,10,5,0"
Height="23"
VerticalAlignment="Top"
HorizontalAlignment="Right"
Click="Button1Click" />
<Canvas Name="CanvasAnimation">
<Rectangle Canvas.Left="408"
Canvas.Top="140"
Height="50"
Name="rectAnimation"
Stroke="Black"
Width="50" />
</Canvas>
</Grid>
From my code behind, i can move the rectangle from its position to a distance:
private void Button1Click(object sender, RoutedEventArgs e)
{
var trs = new TranslateTransform();
var anim3 = new DoubleAnimation(0, -200, TimeSpan.FromSeconds(2));
trs.BeginAnimation(TranslateTransform.XProperty, anim3);
trs.BeginAnimation(TranslateTransform.YProperty, anim3);
CanvasAnimation.RenderTransform = trs;
}
I would like to know how i can move the rectangle from its position to another position by coordinates? Like having the rectangle move to the position of the listbox or textbox
Please note that the below code assumes the coordinates for the button on the canvas and on the form are the same. This is not optimal, you should find a better solution, like putting the button on the canvas.
private void Button1Click(object sender, RoutedEventArgs e)
{
//Point relativePoint = buttonAnimation.TransformToAncestor(this).Transform(new Point(0, 0));
Point relativePoint = buttonAnimation.TransformToVisual(CanvasAnimation).Transform(new Point(0, 0));
var moveAnimX = new DoubleAnimation(Canvas.GetLeft(rectAnimation), relativePoint.X, new Duration(TimeSpan.FromSeconds(10)));
var moveAnimY = new DoubleAnimation(Canvas.GetTop(rectAnimation), relativePoint.Y, new Duration(TimeSpan.FromSeconds(10)));
rectAnimation.BeginAnimation(Canvas.LeftProperty, moveAnimX);
rectAnimation.BeginAnimation(Canvas.TopProperty, moveAnimY);
}
Sorry for the late answer, but it sounds like you want to set a dependency property.
rectAnimation.SetValue(Canvas.TopProperty, 0.0);
rectAnimation.SetValue(Canvas.LeftProperty, 0.0);
This will (instantly) place the rectangle at the top and left of the containing canvas.