Let user resize control (textbox, specifically) in Canvas UWP - c#

I have a canvas with a button that the user can press to add a new textbox to the canvas. How can I make it so the user can resize the text box by clicking and dragging on any of the corners of the textbox. Because the textbox is created in the C# code (not XAML), I would prefer code in C# not XAML.
Thanks
EDIT: My question is different than the one referenced because it is in UWP not WPF. These have very different controls. I would appreciate if you could translate the UWP information into UWP C#

You can use Thumb control instead of a textbox. The thumb control provides the functionality for you to write code to customize the drag and drop behavior. A simple code would be:
<Canvas x:Name="test">
<Thumb Width="100" Height="100">
<Thumb.Template>
<ControlTemplate>
<TextBlock HorizontalAlignment="Center" Text="12345"/>
</ControlTemplate>
</Thumb.Template>
</Thumb>
</Canvas>
A more complex sample could be found from this SO thread from Jay's answer. But please notice you need to customize the logic yourself in order to make it resize like what you need. The reference is just a direction.

Related

Drag and drop onto SwapChainPanel in UWP app

We have a UWP application that uses a SwapChainPanel for rendering 2D content, we'd like to be able to drag and drop files on it.
First approach:
Firstly I just tried using the events on the SwapChainPanel itself, they never get called.
<SwapChainPanel x:Name="swap" AllowDrop="True" DragEnter="Swap_DragEnter" >
</SwapChainPanel>
Second approach:
I then tried putting a transparent rectangle in the SwapChainPanel. The drag events do work now, but the SwapChainPanel now doesn't receive any pointer events at all.
<SwapChainPanel x:Name="swap" >
<Rectangle Fill="Transparent" AllowDrop="True" DragEnter="Swap_DragEnter" />
</SwapChainPanel>
Third approach:
It seems the SwapChainPanel doesn't work like a normal XAML control, so I assumed I'd have to handle the drag events in the c++ code that runs the panel. But there doesn't seem to be any way of doing this, there are only references to the basic pointer events.
...
coreInput_ = renderPanel_.CreateCoreIndependentInputSource(deviceTypes);
coreInput_.PointerPressed({this, &InputManagerImpl::onPointerPressed});
coreInput_.PointerMoved({this, &InputManagerImpl::onPointerMoved});
coreInput_.PointerReleased({this, &InputManagerImpl::onPointerReleased});
coreInput_.PointerEntered({this, &InputManagerImpl::onPointerEntered});
coreInput_.PointerExited({this, &InputManagerImpl::onPointerExited});
coreInput_.PointerCaptureLost({this, &InputManagerImpl::onPointerCaptureLost});
coreInput_.PointerWheelChanged({this, &InputManagerImpl::onPointerWheelChanged});
...
So now I'm not sure how I can peform drag/drop operations? Thanks!
I think you could place your SwapChainPanel inside a Grid, and put the drag and drop onto the grid. You might loose interaction with your render scene though. And, make sure, since it's transparent, it accepts user input.
For example:
<!-- add attributes and drag and drop functionality on Grid -->
<Grid AllowDrop="True" DragEnter="Swap_DragEnter">
<SwapChainPanel x:Name="swap">
</SwapChainPanel>
</Grid>

How to handle Click event on a custom WPF control composed of controls that don't have Click events

I am creating a custom ToolBar control that I will be able to use in my WPF application.
My CustomToolBar control is based on a StackPanel control and will contain multiple CustomToolBarButton controls.
My CustomToolBarButtons are based on a vertical StackPanel and contain an Image control and a Label control.
I want to programmatically create a Click event for my CustomToolBarButtons that will fire when Image or label gets clicked. Unfortunately, neither Image nor Label controls have Click events in WPF.
It's a surprise for me because I am used to WinForms controls and vast majority of them have Click events by default. Do I have to create custom Image and Label controls and create Click events for them or is there a cleaner and simpler way of doing this?
Thanks for any help!
Well, there's not a great and simple way using standard functionality. I got around this by making my own trigger (derived from System.Windows.Interactivity.TriggerBase from the Blend SDK) so that in my projects I can do the following:
<Label>
<i:Interaction.Triggers>
<mu:MouseTrigger MouseButton="Middle" MouseAction="Click">
<i:InvokeCommandAction Command="{Binding Path=Close}" />
</mu:MouseTrigger>
</i:Interaction.Triggers>
</Label>
Effectively the MouseTrigger class will handle MouseDown and MouseUp events from the UIElement it's attached to and use that to invoke the actions associated with the trigger. The code is a bit more complex than just that, though, since I also do mouse capturing & I utilize an internal helper class so that I could add multiple triggers to the same element with only one instance of a helper class handling events & capturing the mouse for that element.
For the actual actions, I just use existing Blend or Prism actions such as InvokeCommandAction.
Here is the project if you're interested. It was too large to paste into this format. It uses some C# 6.0 features but you could easily modify it to work on an older version of C# by removing some null conditional operators. It requires you install the Blend SDK as it depends on System.Windows.Interactivity (should install with Visual Studio as long as you select that option). MouseTrigger is the publicly visible class that is the point of interaction with the functionality. MouseCatcher is the internal helper class mentioned.
I'd recommend not going down the route of custom controls, but rather of using some mechanism (this one or otherwise) to extend the existing functionality using the attached property framework that WPF and XAML bring to the table.
In WinForms you would create custom controls simply to get a nonstandard look, in WPF this is no longer necessary.
The WPF way: instead of making a Stackpanel's children implement Click behaviour, let's make a Button look like the desired Stackpanel.
Could do this setting the Content:
<Button>
<StackPanel >
<Image Source="C:\myFiles\myPic.png"/>
<Label HorizontalAlignment="Center">SomeTxt</Label>
</StackPanel>
</Button>
But this way it still looks like a Button, to overcome this we can set the Template instead:
<Button>
<Button.Template>
<ControlTemplate TargetType="Button">
<StackPanel >
<Image Source="C:\myFiles\myPic.png"/>
<Label HorizontalAlignment="Center">SomeTxt</Label>
</StackPanel>
</ControlTemplate>
</Button.Template>
</Button>
Both solutions will raise a Click event clicking the image or label.

Most simple FrameworkElement to handle HorizontalAlignment and VerticalAlignment?

This is Silverlight.
Initial goal is to display a random element in a Popup with some VerticalAlignment and HorizontalAlignment. I do not want to use VerticalOffset or HorizontalOffset, because there is more to what I really want to do, including some complex bindings.
First attempt was:
<Popup>
<Button
Height="135"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" />
</Popup>
Second attempt was:
<Popup
Height="135"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom">
<Button />
</Popup>
Both were a failure: the Button was always on Top and not Stretch (HorizontalAlignment and VerticalAlignment didn't work).
So I had the idea to encapsulate the element in a simple FrameworkElement:
<Popup>
<Border>
<Button
Height="135"
HorizontalAlignment="Stretch"
VerticalAlignment="Bottom" />
</Border>
</Popup>
And it is working.
But I had to use Border in this example, when I could have done it with Grid and many other FrameworkElement (but not with Canvas or Viewbox or Popup). I'd like to know what is the most simple, efficient and processor-friendly transparent FrameworkElement to encapsulate another element with working HorizontalAlignment and VerticalAlignment? Is it:
Border? (like the above example)
UserControl?
ContentControl?
ContentContainer?
some custom and basic MyFrameworkElement? (might need help for most basic implementation)
something else like Grid?
WPF controls come in two flavors: Ones that interact with users (like accept user clicks like a button, or display text like a text block) and containers that control placement and layout of the previous ones.
Container controls are usually designed to lay out their children in a specific manner. For example, Canvases lay out children by X, Y, Width & Height values. Each one has a specific use, so you must read the documentation or tutorials for these container controls and understand how each works in order to select the appropriate one for a task.
In your case, you want the button to fill all available space in the popup (it seems, it isn't that clear). I know that the Grid does this by default. So I would do the following:
<Popup><Grid><Button /></Grid></Popup>

Add a Behavior to an Image

In my program I have an System.Controls.Image to which I want
to add a shaking Behavior from here Animate Image in button to shake
I copied the ShakingBehavior to my project to it's own class,
and I already have the Blend SDK.
Now I added the XAML Part to my Image
<Image Source="myImage.png" Grid.Row="{Binding Path=Row}" Grid.Column="{Binding Path=Col}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Margin="0">
<i:Interaction.Behaviors>
<local:ShakeBehavior RepeatInterval="5" SpeedRatio="3.0"/>
</i:Interaction.Behaviors>
</Image>
Now I get an error that I cannot get rid of!
(As I do not have an english VS here, I try to translate the message)
The Interaction type has no attachable Behaviors property
probably just a namespace to add (the i alias), but I cannot bring it to work
edit
More information: The Image is contained in a button, which is inside a datatemplate.
And (at best) I want to start the animation when another button in the view is clicked.
(this Behavior shall help to find the button as a hint)
Since Mohib doesn't want to, i will post the correct line that I have missed:
this one should be without those magic unprinted values that can be found in Mohibs answer.
xmlns:i="clr-namespace:System.Windows.Interactivity;assembly=System.Windows.Interactivity"

Bing Maps (Silverlight) maps - specifying canvas to be at foreground through XAML

Below is the XAML code i have for a Bing Maps Silverlight weather related implementation.
Here is what i am trying to do:
Have a bing maps with several (over 100) pushpins- on mouseover - show a contentpopup (canvas=myPopup) below. Simple enough.
Everything works fine - however, when mypopup displays on mouseover, it is not on the foreground (the other pins appear on top of the contentpopup) - hence making it not very readable.
Question:
How do i specifiy the myPopup canvas specified in XAML below to always appear in the foreground, i.e. top most of the Bing Maps silverlight control when a user views it on mouseover.
Thanks!
<Grid x:Name="LayoutRoot" Background="White">
<m:Map x:Name="GlobalMap" Mode="Road" Center="15,7" ZoomLevel="2" CredentialsProvider="{StaticResource MyCredentials}" Margin="-70,-40,-100,-72">
<m:MapLayer x:Name="myLayer">
<Canvas x:Name="myPopup" Visibility="Collapsed" Opacity="1">
<Rectangle x:Name="myPopupRectangle" Fill="White" Canvas.Left="0" Canvas.Top="0" Height="100"
Width="100" RadiusX="15" RadiusY="15"/>
<StackPanel Canvas.Left="8" Canvas.Top="8">
<TextBlock x:Name="myPopupTexts" FontSize="5" Width="100">
</TextBlock>
</StackPanel>
</Canvas>
</m:MapLayer>
</m:Map>
</Grid>
Try adding Canvas.ZIndex to the MapLayer element, give it a large value like 200 or add your push pins to another MapLayer (rather than adding the pins directly to the map) that appears ahead of this popup layer in document order.
I did something similar to this, but took a different approach. What I did was create a custom pushpin template and create a PopUp within the template.
When the user hovers over the pushpin, the popup is displayed. Using the PopUp will solve your problem, since the control will automatically position it on top of everything. Try wrapping the Canvas in a PopPup and see if that works.
hth

Categories

Resources