I'm creating an application (for a tablet PC) where a user will fill out an inspection form. As a final step, the director must be able to sign it (along with a few other people).
Since I want to keep my form small and concise, I was looking to create a click event on an image control which would pop up my signature canvas window.
XAML Code for my Image control
...
<DockPanel HorizontalAlignment="Stretch" Name="dpDirectorImg" VerticalAlignment="Stretch" Grid.Column="1" Grid.Row="8">
<Image Height="Auto" Name="imgDirectorSignature" Stretch="Uniform" Width="Auto" MouseDown="imgDirectorSignature_MouseDown" />
</DockPanel>
...
VB Code
Private Sub imgDirectorSignature_MouseDown(sender As Object, e As System.Windows.Input.MouseButtonEventArgs) Handles imgDirectorSignature.MouseDown
MsgBox("Hello World")
End Sub
For example, in the following screenshot the user would touch / click in the red rectangle (which contains an Image control):
Which would prompt this window:
My problem: I cannot seem to trigger the event on the Image. I have tried TouchDown, MouseDown, StylusDown, GotFocus (with property Focasable set to true) and nothing seems to trigger it.
Well now that we found out what was the problem.
How about you stop using empty images for the future and instead you use Rectangle:
<DockPanel HorizontalAlignment="Stretch" Name="dpDirectorImg" VerticalAlignment="Stretch" Grid.Column="1" Grid.Row="8">
<Rectangle MouseDown="imgDirectorSignature_MouseDown" />
</DockPanel>
If the rectangle has any background color by default you can change it to transparent
Background = Transparent
Glad I was able to help you out on this and notice, when Background or Source of an Image is NULL, the hit testing in wpf will not work. That is by design.
Set Background to transparent or any color you like :)
Related
I have run into a very strange issue today:
I have a popup menu that opens when I hover above an image. The popup menu is positioned right of the image.
this popup menu is templated to look like a rectangle with a little arrow pointing to the image
the menu contains clickable elements, so I need to be able to move the mouse from the image to the menu without it closing in between, and this is where I get confused: if I move the mouse right over the tip of the arrow and then the menu, everything works fine. If I move the mouse over the transparent space between the image and the menu (above or under the arrow), the menu disappears.
Here is the template for the menu:
<Popup AllowsTransparency="True" Name="c_popup" Width="300" PlacementTarget="{Binding RelativeSource={RelativeSource TemplatedParent}}" Placement="Right">
<Grid Background="Transparent">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="10" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Path Data="M 0 10 L 10 0 10 20 Z" Stroke="#252C37" Fill="#252C37" Margin="0,18,0,0" Grid.Column="0" />
<Grid Grid.Column="1" Background="#252C37">
<TextBlock Text="{Binding Name}" Margin="20,10,0,0" FontSize="18" Foreground="White" HorizontalAlignment="Stretch" VerticalAlignment="Top" TextWrapping="WrapWithOverflow" />
</Grid>
</Grid>
</Popup>
you'll notice that I specifically put Background="Transparent" and not Null (I am aware of the effect this as on the hitTesting, see this question)
funny thing is, though: If I put Background="#01000000", it works as expected. (And I get almost what I want, since this is almost a transparent background)
but I would still like to know what is going on there...
I suspect it has something to do with the fact that this is a popupmenu. I assume WPF does something to remove the hitTesting on any surface that is transparent in a popup menu, either when the background is null (which is expected) or even if it is specifically set to transparent (not expected). Can anyone confirm this?
Converting my comment to an answer.
This seems to be more of a "Windows OS" issue than WPF specifically in the way AllowTransparency="True" at a Window level makes the system ignore the element for mouseover events when Background="Transparent" or Opacity="0" on the element..
A detailed explanation of this behavior can be found Here
Adding the MSDN answer just in case the link goes missing later:
Windows supports transparency at the HWND level through a feature called "layered windows".
Layered windows are represented by a bitmap.
The Operation System(OS) renders the bitmap whenever it needs to.
For the OS need to respond very quickly to mouse movement, Windows uses a dedicated Raw Input Thread (RIT).
RIT runs in the kernel and handles the singals from mouse hardware.
RIT can scan over the HWND hierarchy to detect which window the mouse is over.
For normal windows, the RIT checks the mouse position against the window's rectangle.
For layered windows, the RIT looks in the bitmap that specifies the content for the window and checks the effective transparency at that location. The effective transparency can be affected by opacity, color and alpha channel.
If the pixel is 100% transparent, the RIT skips the window and keeps looking. This point is the reason that MouseMove event is not fired.
If the Background of window and control are both Transparent, all the pixels that represent this control(Canvas in your example) in the layered windows are totally transparent. As described above, RIT will skip them and never send WM_MOUSEMOVE message.
So if you want only show up the control only when the mouse is over and otherwise and the window is transparent, you have to make the control not 100% transparent.
Something to note in this case is, even though Popup is within a Window that does not have AllowTransparency="True", Popup generates a Chrome-less window itself and the AllowTransparency="True" on the Popup affect this new chromeless-Window the same way as mentioned in the MSDN link above.
If this control were just a standard control like Button/Rectangle... then just setting the Background="Transparent" would make it work fine and not have this issue.
I am trying to load a UserControl in the Window by using content control's content property in code behind. Every thing is fine, but my friends were not able to see all the control on the page due to resolution problem. How can I fix this to have scroll bar. I have tried putting ScrollViewer also, but it's not working. So, my solution works on the bigger Window which developed, but its not working on the Smaller resolution windows.
Sample code structure of loading the UserControl:
Window.Xaml
<ScrollViewer>
<ContentControl Name="ContentX" Margin="15,10,15,0" HorizontalAlignment="Center" VerticalAlignment="Center">
<Label FontWeight="Black" FontSize="18" FontFamily="Calibri">Some Content</Label>
</ContentControl>
</ScrollViewer>
Window.Xaml.cs
ContentX.Content = new UserControl();
UserControl.Xaml
//Contains the Code for User Control
I got it solved my Content Control is in another Grid Column where i fixed the width and height to be *, now i removed it it's working fine when i place it inside a Scroll Viewer
I have the following piece of code, which is part of a WPF 4 UserControl:
<Popup x:Name="CantoPopup" IsOpen="False" PlacementRectangle="50,-100,500,120"
AllowsTransparency="True" PopupAnimation="Fade"
StaysOpen="True" Width="500" Height="120">
<Border BorderBrush="#FF120403" BorderThickness="1" CornerRadius="10" Background="#FF9350">
<s:SurfaceScrollViewer x:Name="IndexScroller" Width="500" Height="120" Margin="10" VerticalScrollBarVisibility="Disabled" HorizontalScrollBarVisibility="Visible">
<DockPanel x:Name="InnerIndexPanel" />
</s:SurfaceScrollViewer>
</Border>
</Popup>
The DockPanel is then populated in the code-behind with a collection of TextBlocks. Basically, I am trying to build a scrollable horizontal list of touchable items.
Now, I would like to detect which textblock was touched by the user. However, neither adding a TouchDown event handler to the TextBlocks nor using TouchExtensions to handle tap gestures worked. Can someone please point me in the right direction?
Under the covers, Popup creates another hwnd to render its content into. This is different from all other WPF controls. You need to register this hwnd with the Surface SDK so it will start sending touch events to it. Use this to do that: http://msdn.microsoft.com/en-us/library/microsoft.surface.presentation.input.touchextensions.enablesurfaceinput.aspx
I found out that the point is that the Popup component has some peculiarities :) In this case, it seems that it did not detect neither TouchDown events nor PreviewTouchDown ones. Therefore, I resorted to creating a UserControl made of a Canvas containing the code above and then making such control visible on top of the rest whenever I needed the popup to open. I do not know whether this is the best solution, but now it reacts as expected.
I am trying to figure out how to connect windows so the slide out using a small button from the left or right of a main window. What I am trying to do is create a main form with 2 windows connected to it. For one of the windows when the user presses a button on the main window it makes the window seem to slide out rather than pop up. Here is where I got the idea http://www.youtube.com/watch?v=CVlSj0yr3rg&feature=related ..The user then changes a value and the main windows is updated with new information. Honestly I have finished writing all my code and got everything working in Windows Forms in visual studio 2010 (with pop up windows).But I am thinking to make a more appealing gui WPF is the way to go, plus I like learning about it. If you have any forums, tutorials or general answers that would be great.
OK, so judging from the video you really want some kind of expander that opens and not a Window. A Window is an area with border, and the standard buttons and titlebar at the top.
This can be done with a grid with two columns. One is set to Auto width, one is set to * width. In the Auto sized one you can put your expanding content, and have your always visible content in the other.
The simple way to do this:
The Xaml
<Window
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:StackOverflow"
x:Class="MainWindow"
x:Name="Window"
Title="MainWindow"
Width="640" Height="480">
<Grid x:Name="LayoutRoot">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" MinWidth="7"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Grid x:Name="ExpandoGrid"/>
<Button Content="..." Grid.Column="0" HorizontalAlignment="Right" Margin="0" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" Width="6" Height="40" Click="Button_Click"/>
<Grid x:Name="OtherContentGrid" Grid.Column="1" HorizontalAlignment="Left" Height="100" Margin="-7,0,0,0" VerticalAlignment="Top" Width="100"/>
</Grid>
</Window>
The Code-behind
Imports System.Collections.ObjectModel
Class MainWindow
Public Sub New()
InitializeComponent()
End Sub
Private Sub Button_Click(ByVal sender as Object, ByVal e as System.Windows.RoutedEventArgs)
If Me.ExpandoGrid.Width = 7 Then Me.ExpandoGrid.Width = 200 Else Me.ExpandoGrid.Width = 7
End Sub
End Class
This is by no means the complete way, or the best way. It is one of the simplest to implement though. A better way would be with a ViewModel which would handle the state of the expanded area, along with some animations to make it a smooth transition. If you want the sliding behaviour that is done in that video, animations are where it is at. If you are using Blend, then you have the right tool for animations.
Personally I would have this Windows ViewModel have a property (lets call it DrawerExpanded as Boolean) that a customized Expander would bind its IsExpanded property to. I would then create an open animation that sets the width of the content in the expander, and a close animation that sets the width to 0. Additionally, in each of these I would probably include setting the visibility and opacity to make the effect better and not weird. So lets say expand animation sets Width to 350 at .5 seconds, Visibility to visible at .5 seconds, and then opacity from 0 to 100 from .5 seconds to .7 seconds. That way the drawer slides out and the content fades quickly into view.
If you want a code example of that, you may have to give me a few mins.
I would really just take the easy/friendly route of creating Visual States in Expression Blend. There's basically just an "in state" and "out state", and an InteractionTrigger that allows the control to trigger the state change. Its awesome and extremely user friendly.
No code behind :) Hope it helps you!
As a bonus, you can easily add transition effects just like in a powerpoint. The xaml code gets pretty verbose, but working in Blend allows you to use the IDE to manage everything you add visually.
You can even use the Interaction Trigger to toggle between visibility states of the other controls, rather than writing converters, etc.
There is a command property in wpf that I am trying to execute on an image click. I am basically changing the style of a scroller. I downloaded sample styles from here and after changing my style I end up with something like:
ok so let me explain. on the top there is an arrow pointing upwards on top of an image. I plan to get rid of the top arrow but the reason why I need it is because in the xaml it has a command that when clicked it scrolls upward. the code for that up arrow is:
<RepeatButton
Style="{StaticResource ScrollBarButton}"
Margin="0,15,0,0"
VerticalAlignment="Top"
Background="#FFFFFFFF"
Grid.Row="0"
Command="{x:Static ScrollBar.LineUpCommand}" <!-- This is the line that enables to scroll upwards when clicked -->
theme:ScrollChrome.ScrollGlyph="UpArrow"
RenderTransformOrigin="0.5, 0.5">
<RepeatButton.RenderTransform>
<ScaleTransform ScaleX="4" ScaleY="2"/>
</RepeatButton.RenderTransform>
</RepeatButton>
In short I am interested in the following property:
Command="{x:Static ScrollBar.LineUpCommand}"
It would be nice if I could get rid of the top arrow and place that command in the image instead. The problem is that the image control does not have the property command. I know I can make the alpha of the top arrow equal to 0 and make it appear like there is only an image but I am curios of understanding how does this work and moreover I would like to add more functionality such as changing the image appearance on mouse enter etc..
Create a button with control template just having an image and bind to the
Command of the button. More on this can be found here:
Attach ICommand in WPF UserControl
Or try using eventtocommand available in mvvm light tookit