How do I make a WPF popup draggable using a thumb? - c#

I've searched long and hard to find an example of this on the net. I've seen the alternative methods for this but I want to specifically use a thumb. In trying to hash out a solution I've been unable to get the functionality right/working as I'm fairly new to WPF. I'd be grateful if someone could give an example of how you may implement the above.
Cheers

A Popup doesn't give you an obvious way to move it; you can only place it relative to its placement target. However it does give you and additional offset relative to the placement target and that's enough to move it anywhere.
Here's a working markup-only solution that demonstrates a draggable Popup using a Thumb using Markup Programming. There is a text box that has a popup that pops up when the text box receives the keyboard focus. The popup has some text and a thumb.
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:p="http://markupprogramming.codeplex.com/markup/programming"
Height="300" Width="300">
<Grid>
<StackPanel>
<TextBox x:Name="textBox1" Width="200" Height="20"/>
</StackPanel>
<Popup Name="popup" PlacementTarget="{Binding ElementName=textBox1}"
IsOpen="{Binding IsKeyboardFocused, ElementName=textBox1, Mode=OneWay}">
<StackPanel Orientation="Horizontal">
<TextBlock Background="White" Text="Sample Popup content."/>
<Thumb Name="thumb" Width="20" Height="20"/>
</StackPanel>
<p:Attached.Operations>
<p:ScriptHandler Path="#FindElement('thumb').DragDelta">
#AssociatedObject.HorizontalOffset += #EventArgs.HorizontalChange;
#AssociatedObject.VerticalOffset += #EventArgs.VerticalChange;
</p:ScriptHandler>
</p:Attached.Operations>
</Popup>
</Grid>
</Window>

Related

How to click WPF ScrollViewer down button

Following picture shows my project.
Here is XAML code for your testing needs.
<Window x:Class="MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="200" Width="525">
<ScrollViewer Name="ScrollViewer1" Height="67" VerticalAlignment="Top">
<StackPanel>
<TextBox Name="TextBox1" Text="TextBox1"/>
<TextBox Name="TextBox2" Text="TextBox2"/>
<TextBox Name="TextBox3" Text="TextBox3"/>
<TextBox Name="TextBox4" Text="TextBox4"/>
<TextBox Name="TextBox5" Text="TextBox5"/>
<TextBox Name="TextBox6" Text="TextBox6"/>
</StackPanel>
</ScrollViewer>
</Window>
Following picture shows my question;
So, how to click WPF ScrollViewer down button in order to go end of ScrollViwer?
A solution could be to subscribe to the click of that button like here https://stackoverflow.com/a/4932118/6890102, then call the ScrollToEnd() method of the ScrollViewer. But there might be a better solution.
Right-Click on ScrollViewer->Edit Template->Edit a Copy, to see the Scrollviewer's Template. The ScrollViewer contains a ScrollBar. A ScrollBar contains, RepeatButton, and a Track. The RepeatButton is responsible for the up and down movement of the scrollbar. Try checking it. You may find some idea on how to implement your objective.

How to Draw Content in Non-Client Area Properly with Regular Caption Buttons

I am trying to make a window with the default caption buttons and title bar, and still be able to place arbitrary content within the window chrome; however, all the solutions I have tried leave an approximately 5 unit margin to the right of the caption buttons. Here is a basic example:
<Window x:Class="SemiCustomWindowChrome.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:SemiCustomWindowChrome"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525" Name="Window">
<WindowChrome.WindowChrome>
<WindowChrome UseAeroCaptionButtons="True" ResizeBorderThickness="5" GlassFrameThickness="1,28,1,1"/>
</WindowChrome.WindowChrome>
<Window.Template>
<ControlTemplate>
<AdornerDecorator>
<ContentPresenter Content="{Binding ElementName=Window, Path=Content}"/>
</AdornerDecorator>
</ControlTemplate>
</Window.Template>
<Grid>
<StackPanel Orientation="Horizontal" VerticalAlignment="Top">
<Button Content="Click me daddy!" WindowChrome.IsHitTestVisibleInChrome="True" Height="28"/>
<TextBlock Text="Custom Window Test" Margin="6.5"/>
</StackPanel>
<TextBlock VerticalAlignment="Center" HorizontalAlignment="Center" Foreground="White" FontFamily="MS Calibri" FontWeight="ExtraLight" Text="Hello There"/>
</Grid>
The above code produces this.
To be clear, I would like to remove the white padding to the right of the caption buttons in the window chrome so that the window is exactly the same as any other, with the only difference that I can put controls in the non-client area (the window chrome).
All help is appreciated!
If there is a more stable way to do it with DWM that does not include the use of a WindowChrome element I would appreciate if someone could give me an example.
WindowChrome.WindowChrome>
<WindowChrome GlassFrameThickness="0.5,28,0,0.5" NonClientFrameEdges="Right"/>
</WindowChrome.WindowChrome>
<Window.Template>
<ControlTemplate>
<ContentPresenter Content="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType=Window}, Path=Content}"/>
</ControlTemplate>
</Window.Template>
This took a very long time to find. Originally I thought that the WindowChrome class was just completely broken, and it is to an extent, but I managed to use it anyways. The other solutions I came up with were a lot more complicated, and eventually, it just seemed a lot easier to just try and mess around with WindowChrome. I will work on a modified version of the class specifically for Windows 10, but until then, this works. I hope this helps somebody.
To use this code, just put it in at the top of the content area in the XAML for a window.

Open popup at the location of the button clicked

I am trying to create a popup that opens similar to the window preview option in Windows 8 taskbar. Basically, when I click or hover on a button, it opens a popup with basic information just above the button. Here is an example.
Right now, I am able to open the popup at either the extreme left or extreme right side of the page, using the code below.
<Frame x:Name="PopUpFrame" HorizontalAlignment="Left" Visibility="Hidden" Height="400" Margin="10,10,0,0" Grid.Row="1" VerticalAlignment="Bottom" Width="400" Source="/BasicApp;component/StandingOrderPopUp.xaml" NavigationUIVisibility="Hidden"/>
I have 3 different buttons in the button bar, so I cannot set the fixed margin. I am trying to set the same in code but I am unable to get the absolute position and convert it to margin property. I am not sure, if there is a better solution either.
Edit:
Tried using popup but it doesn't open on button click.
<Popup x:Name="PopUpFrame" Placement="Top" PlacementTarget="{Binding ElementName=StandingOrderButton}" Width="400" Height="400">
<DockPanel Background="#770081a7">
<Canvas DockPanel.Dock="Bottom" x:Name="PopupButtonBar" Height="50" VerticalAlignment="Bottom">
<Button Height="30" Width="125" HorizontalAlignment="Right" VerticalAlignment="Center" Canvas.Top="10" Content="CLOSE" Foreground="White" Background="#ff0081a7" BorderBrush="White" FontFamily="Trebuchet MS" Canvas.Left="10" />
</Canvas>
<Label Margin="5,0,0,0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" DockPanel.Dock="Top" Content="STANDING ORDERS" Foreground="#ffffffff"></Label>
<Grid DockPanel.Dock="Top">
<Border BorderThickness="2" BorderBrush="#FFff7a00"></Border>
<RichTextBox Margin="2" Foreground="#FF0081a7" FontFamily="Trebuchet MS" IsEnabled="False"/>
</Grid>
</DockPanel>
</Popup>
And here is the event handler.
Private Sub StandingOrder_Click(sender As Object, e As RoutedEventArgs)
PopUpFrame.Visibility = Windows.Visibility.Visible
End Sub
Edit:
Never mind. I am an idiot. Instead of setting IsOpen property, I set the visibility. :(
It works perfectly, although, I had to copy the whole design from the separate page to this one. Still better than nothing. Only problem now is if I click on something else, I will have to write code to make sure popup is closed.
You can use a Popup control, coupled with it's Placement property to display your popup based on the current location of your buttons.
<Popup Placement="Top" PlacementTarget="{Binding ElementName=yourButton}" ... />
Inside your Popup, you can place your UserControl or any content element which will act as the popup's content.
See here for further information on popup placements, and here for a tutorial on WPF Popup controls.
Think about using ContextMenu, and set it's content you whatever you want. Thats is the solution for you.
This is how i defined one of my popups:
<Popup x:Name="btnPowerPopup" Placement="Mouse" StaysOpen="False">
....
</Popup>
you can user from the code behind on a button click or something :
btnPowerPopup.IsOpen = true;
and when the job is done:
btnPowerPopup.IsOpen = false;
But StaysOpen="False" let's you close the PopUp when clicking somewhere else.

Position the Popup control in the screen and Textblock text center

I'm quite new in C# WPF. I want my Popup control to be positioned in a certain coordinates of the user's screen. and I want to make my textblock text center in the textblock itself. I tried to add a block but it doesn't work. Look at my XAML codes: (I'm 97% done in my personal project. :) )
Also, look at my screenshot, I put a red box there, I want my popup control to be there, although it is not my priority cause the original position is quite fine with me, but I would be glad if this will be moved.
Next, look at the annoying text, it is not centered.
The current position of the popup is in the left most and upper most part of my screen.
<Window x:Class="KeyLocks_Notifier.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<Popup Name="Popup1" AllowsTransparency="True" PlacementRectangle="0,0,30,50" Placement="Center"
PopupAnimation="Fade">
<Border BorderBrush="{x:Null}" Height="50">
<TextBlock Name="myPopupText"
Background="#FF9700FF"
Height = "40"
Width="180"
Foreground="White" FontWeight="Bold" FontSize="16" HorizontalAlignment="Center" VerticalAlignment="Center">
<TextBlock.Effect>
<DropShadowEffect/>
</TextBlock.Effect>
</TextBlock>
</Border>
</Popup>
</Grid>
</Window>
On the window :
In XAML there is a WindowStartupLocation on the root level with 3 options (Manual, CenterScreen, CenterOwner)
If you want a custom Location on your screen you need to set WindowStartupLocation to Manual and set the Top & Left with pixel
For your popup :
You can set the Placement to custom
Example Here
And for your text position Here

Layout two controls on a line in a stretchable WPF window

Here's a fairly common UI pattern: Text box that contains a path to the left, and a Browse button to the right of it. If the window resizes, the button stays to the right, but the text box stretches to reveal more/less of the path. So in the good old days of anchors, the button would be anchored to the right and the text box would be anchored both left and right.
Trying to replicate this in WPF seems to be worryingly difficult.
If I create a new window, it comes with a Grid layout by default. I place my text box to the left and size it appropriately, then place the button to its right. HorizontalAlignment for the text box is Stretch and for the button it is Right.
In my mind, this works as described, but in real life the text box doesn't resize at all, but instead tries to center itself in the window, while the button acts as expected. What gives?
Here is my XAML:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" mc:Ignorable="d" xmlns:d="http://schemas.microsoft.com/expression/blend/2008" xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" d:DesignHeight="241" d:DesignWidth="414" SizeToContent="WidthAndHeight">
<Grid>
<TextBox Height="23" HorizontalAlignment="Stretch" Name="textBox1" VerticalAlignment="Top" Margin="12,11,101,0" />
<Button Content="Button" Height="23" HorizontalAlignment="Right" Margin="0,11,12,0" Name="button1" VerticalAlignment="Top" Width="75" />
</Grid>
</Window>
You would create another GridControl with two columns, one with a fixed width for Browse button and another one for the TextBox.
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="75" />
</Grid.ColumnDefinitions>
<TextBox Grid.Column="0" />
<Button Grid.Column="1" />
</Grid>
You can use a DockPanel and set LastChildFill property to true to ensure that the textbox uses all the available space:
<DockPanel LastChildFill="true">
<Button DockPanel.Dock="Right">Browse</Button>
<TextBox>Content</TextBox>
</DockPanel>

Categories

Resources