WPF Controls Dll question - wpf

I've started work on a WPF controls dll which will be referenced from winforms applications.
My first control in this project is a simple container control. It's purpose in life is to provide a modaless, transparent docking window to the Winforms app.
My problem with this control is that I can't get it to move when I try to drag it. I can move it if I don't put it into a .dll. Inside the dll, Canvas.GetLeft - returns an invalid number, and I don't know how to fix this.
Here's the bulk of the XAML for this control:
<Grid Height="Auto">
<Grid.Resources>
<LinearGradientBrush x:Key="BackBrush" EndPoint="0.5,1" StartPoint="0.5,0">
<GradientStop Color="#C4000000"/>
<GradientStop Offset="1" Color="#66000000"/>
<GradientStop Color="#61000000" Offset="0.50400000810623169"/>
</LinearGradientBrush>
</Grid.Resources>
<Border Height="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" Width="Auto" Margin="0,0,0,0" BorderBrush="#FF000000" BorderThickness="2,2,2,2" Background="{StaticResource BackBrush}" Opacity="1" CornerRadius="8,8,8,8">
<StackPanel Background="{x:Null}" Opacity="1" Height="Auto" Width="Auto" HorizontalAlignment="Stretch" VerticalAlignment="Top" x:Name="spWhatAreYouDoing">
<ContentControl></ContentControl>
</StackPanel>
</Border>
<Thumb Background="{x:Null}" Opacity="0" DragDelta="onDragDelta" x:Name="panelthumb"/>
</Grid>
I've hooked the Thumb's onDragDelta event in the code behind and use that to drag this window around. This works fine when I use it in the same .exe.
public void onDragDelta(object sender, System.Windows.Controls.Primitives.DragDeltaEventArgs e)
{
Canvas.SetLeft(this, Canvas.GetLeft(this) + e.HorizontalChange);
Canvas.SetTop(this, Canvas.GetTop(this) + e.VerticalChange);
}
When I take this same code out of the .exe and place it into a .dll then reference that .dll and use the control from my exe - it won't drag anymore. The window displays but won't move.
The reason it won't be moved is because Canvas.GetLeft(this) is returning an invalid number. Why? Although the destination for this control is usage by a Winforms app, I find this same behavior when I use it from a WPF app without any ElementHost intervention.
Edit - when I host this control directly within my Winforms app using ElementHost I can move the window. But window transparency is lost. And so the entire reason for moving to WPF for this form is invalid.
So I have done this wrong - what is the right way to call GetLeft from within a control hosted from a .dll?

I suggest you first host the WPF control inside a WinForm. Disable all the border properties of the WinForm...so your control looks as if it is all by itself. Then use this WinForm as the primary means of using your control.
This way you get access to all the related functionality.
In a gist >>> XAML inside a standalone Winforms host. >>> Winform to be used as control in other Winforms.

Whew. I found this link, and it is the answer I needed to get this to work.
http://social.msdn.microsoft.com/Forums/en-US/wpf/thread/281a8cdd-69a9-4a4a-9fc3-c039119af8ed
Instead of using Canvas.GetLeft, I am now using code which obtains the absolute locatin of this control and then raises an event which containers can monitor to know when to move:
'// Get absolute location on screen of upper left corner of button
Dim locationFromScreen As Point = Me.PointToScreen(New Point(0, 0))
'// Transform screen point to WPF device independent point
Dim source As PresentationSource = PresentationSource.FromVisual(Me)
Dim targetPoints As System.Windows.Point = source.CompositionTarget.TransformFromDevice.Transform(locationFromScreen)
Dim left As Double = targetPoints.X
Dim top As Double = targetPoints.Y
left += e.HorizontalChange
top += e.VerticalChange
Canvas.SetLeft(Me, left)
Canvas.SetTop(Me, top)
'spread the news
PaletteMoved(New DockingPaletteEventArgs(left, top, e.HorizontalChange, e.VerticalChange))

Related

Debugging resource value problems in XAML and vb?

I have what seems like a straightforward problem: make an application which can handle any resolution display.
Background:
This is a display-only application (no user interface). It is for display of information, and I've made a test app to work out an issue. Have spent a few days trying to find a solution to this one tiny problem. Either need a clever programming solution (which has thus far eluded me) or a different way of approaching the problem (again, has been elusive).
This is a WPF application with VB.net code behind. The composition of the one and only window needs to maintain the same relative layout to the display components, and the application is intended to run full-screen (this demo runs in a window, so I can resize it easily and test different "screen layouts").
All but one part of the layout works fine.
The part with the problem is a "bar" which is intended to animate up or down, depending on circumstances. The size of the bar already changes appropriately, depending on the size of the application window. However... the distance the bar travels is dependent on the size of that bar; the shorter it is, the fewer pixels it has to travel, and conversely, a higher resolution screen necessitates it travel further. Animation is accomplished by changing the height of a grid object which contains both a rectangle (the bar) and a viewport which in turn has a textblock object.
I've created a resource value in XAML with a value which represents the default height of the grid object which contains the bar. If that resource is bound to the value of the keyframe as a static resource, the value is passed to storyboard and the animation happens. However, I have not been able to change the value in this configuration. When the size of the window changes, VB code attempts to change the resource key value, but no joy. Have also tried this with the binding done as a dynamic resource.
Lots of reading shows that some bindings into XAML work, while others (such as keyframes) aren't so lucky; something about "being freezable," which seems silly, as this shouldn't be that hard. Other things I've read suggest that the "fix" is to implement solution in the code behind. Most don't provide any other info on how that might be done, and the few other items suggestion methods which seem absurdly circuitous.
Here is the XAML, with some inline comments to point out what's going on:
<Window x:Name="SmartClock" x:Class="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:WpfApplication3"
xmlns:System="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="MainWindow" Height="600" Width="800">
<Window.Resources>
<!-- Set a variable (resource) to be used as the height value in animation -->
<System:Double x:Key="OnAirBarUp">84</System:Double>
<!-- Simple keyframe animation, which slides a bar with text into view -->
<Storyboard x:Key="story_OnAirUp" x:Name="OnAirUp">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid_OnAir">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<!-- ****** HERE'S WHERE THE "FUN" BEGINS :/
This line needs to have a target value which changes, depending on the
height of objects in the window, and those are affected by the size
of the window. The intention is to make this a full-screen app, but
can be used on many different monitors, so the resolution is not known
at design time.
The resource I set earlier in the XAML ("84") will be used for this
keyframe value, and the animation works... but is only "correct" for
the default window size.
(yes, I know that the bar starts in the "up" position currently, but that
is just to help me see it as I debug this... when the button is pushed,
the bar should instantly disappear, and then slide back on to the screen
to the same position).
*************************************************************************** -->
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="{StaticResource ResourceKey=OnAirBarUp}"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<!-- Animation is triggered by clicking the button -->
<Window.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button1">
<BeginStoryboard Storyboard="{StaticResource story_OnAirUp}"/>
</EventTrigger>
</Window.Triggers>
<!-- Here we setup the page -->
<Grid x:Name="grid_Page" ShowGridLines="True" >
<Grid.RowDefinitions>
<RowDefinition Height="3*"/>
<RowDefinition Height="4*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<!-- This is "status" grid at the top of the page -->
<Grid x:Name="grid_Top" Grid.Row="0" d:LayoutOverrides="LeftMargin, RightMargin, TopMargin, BottomMargin" ShowGridLines="True" >
<Grid.RowDefinitions>
<RowDefinition Name="row_ProgramName" Height="1*"/>
<RowDefinition Name="row_Status" Height="1*"/>
</Grid.RowDefinitions>
<Viewbox x:Name="viewbox_ProgramName" Grid.Row=" 0" Margin="0" Stretch="Uniform">
<TextBlock x:Name="textblock_ProgramName" Text="Some text on top" Background="#FFFFFF12"/>
</Viewbox>
<!-- This creates a grid which will hold the "ON AIR" bar -->
<Grid x:Name="grid_OnAir" Grid.Row="1" VerticalAlignment="Bottom" ShowGridLines="True" Height="84" >
<Rectangle x:Name="rectangle_OnAir" Fill="#FF90A436" RadiusX="20" RadiusY="20" Margin="10,0" Height="83"/>
<Viewbox x:Name="viewbox_OnAir" Grid.Row="1" Margin="0" Stretch="Uniform">
<TextBlock x:Name="textblock_OnAir" Text="ON AIR" FontSize="64" VerticalAlignment="Top" FontWeight="Bold" Background="#FFDC0000" Margin="0" HorizontalAlignment="Center" />
</Viewbox>
</Grid>
</Grid>
<!-- This is a big ugly button for triggering the storyboard -->
<Button x:Name="button1" Content="Button" Margin="0" Grid.Row="1" FontSize="26.667" HorizontalAlignment="Left" Width="257"/>
</Grid>
</Window>
And here is the VB.net code which also has copious comments:
Class MainWindow
Private Sub MainWindow_SizeChanged(sender As Object, e As SizeChangedEventArgs) Handles Me.SizeChanged
' Set the size of items on the screen based on the size of the window.
' "rectangle_OnAir" is the rectangle (the "On-Air" bar for the display)
' "viewbox_OnAir" allows the textblock to properly scale.
' "grid_OnAir" is the container which will be made taller and shorter
' through animating the "height" property. This allows the contents
' to slide up and down in their region of the screen.
' Since the window can be any size, we adjust the height of the
' controls to accomodate.
rectangle_OnAir.Height = grid_Top.ActualHeight / 2
viewbox_OnAir.Height = grid_Top.ActualHeight / 2
grid_OnAir.Height = grid_Top.ActualHeight / 2
' Set the height of the dynamic resource "OnAirBarUp" to a value
' which equals the height of "rectangle_OnAir".
' This will be used in the animation to allow the whole rectangle to
' be displayed.
Resources("OnAirBarUp") = grid_Top.ActualHeight / 2
End Sub
End Class
This is one version of many permutations.
When the code runs without re-sizing the window, this is what it looks like:
This is the default layout of this test page... the "On Air" bar is visible, and pressing the "button" causes it to disappear for a moment, and then immediately animate upwards into the current position
With the window small, the animation causes the bar to overshoot the location where it need to be (the grid height value is too large for this size window
Making the window larger than default has the opposite effect on the animation; the bar undershoots the landing location.
I've contemplated wrapping the whole display in a viewbox control, so the whole mess can scale to fit whatever display, and tried some of this, with less-than-stellar results. It was overly complicated, and there are distortions in the graphics and text.
From what troubleshooting I could do, it seems that the resource value does change, but not the value at the binding point; I'm pretty much stuck with whatever value was used at the moment the application was launched.
It seems odd to provide a framework for dynamically-configurable layout, and for extensive animation capabilities, and then have it hamstrung by those two aspects not being able to "play nice" together because a simple double value can't be passed from the code to the layout markup.
Please excuse the length of the post; I'm trying to be thorough, and trying to anticipate what someone might write in response. Also please excuse the hideous colors of the sample -- what was an aid to me during the layout of this test, not intended for the final application.
Ideally, the best solution would allow for any size display, without the program having any foreknowledge of that resolution. Also, being able to resize during program execution would be nice, in case the program can be used (after all) in a less-than-full-screen arrangement. In that case, it would need to be able to gracefully handle most reasonable window sizes (I'd have to code in some lower boundary limits to the window size).
Whatever solution I use, it would need to be able to handle other similar animation needs (other parts need to move on and off the screen, moving the correct amount for the given circumstances).
I had posted this last night on both Stack Overflow and on Microsoft's MSDN forums, and got a good reply on MSDN. That pointed me in the right direction, and I posted a follow-up message with a detailed description of what worked for me. Here is that follow-up report:
Andy,
Thanks for the quick and detailed reply!
I'll start with this part: It now works.
It did take me a couple more hours of groping (using your clues) to get there. I started this reply at that time (about four hours ago), but persistence paid off.
-------------
You say: "I get that you're animating the bar but not what it's relative to and where it's coming or going to."
I'm guessing you mean literally, as in where on the screen, as opposed to conceptually (as in purpose).
The literal "where" is to have the bar rise out of the middle third (approximately) region of the screen (divided horizontally). The whole application is a clock with some value-added features for use in a newsroom. I already have a working clock based generally on this design, but the "On Air" bar isn't implemented yet. This will be triggered by an event over a network socket connection, quite literally when the studio is "on air." When that happens, the text in the upper third of the screen is shrunk gracefully as the "on air" bar rises up, essentially halfway into the top third region.
The animation works properly if I don't resize the window. Since I don't know what size monitors will be used in the different implementations of this, and since this will end up being at some of our other facilities which do the same thing, I need to build it at this stage so it is flexible enough to handle a 1024x768 screen or a 1920x1080, or something in-between, or 4K, or whatever.
I could make the bar a fixed size, but that would go against the balance of the layout (aesthetic concern) and the readability of right-sized text (usability concern).
There are to be other status fields which will be able to move into view, depending on circumstances (other things happening in real time, triggered by events over the computer network), which will need to have similar flexibility of the positioning of the animations.
Looking over the marquee code you pointed out to me, it seems that binding is done to an object, but I'm unsure how that method could change the distance that a keyframe could move the object, just adjust the properties of the object being moved.
-------------
I looked over the "marquee" code, though it took some patience to dissect it. The C# isn't too bad, but I'm not fluent, so I turned to an online code converter to translate it to VB:
Public Partial Class MainWindow
Inherits Window
Public Sub New()
InitializeComponent()
End Sub
Private SBMarquee As Storyboard
Private XAnimation As DoubleAnimation
Private Sub Window_ContentRendered(sender As Object, e As EventArgs)
SBMarquee = TryCast(Me.Resources("SBmarquee"), Storyboard)
XAnimation = TryCast(SBMarquee.Children(0), DoubleAnimation)
XAnimation.[To] = MarqueeContainer.ActualWidth * -1
AddHandler Me.SizeChanged, AddressOf Window_SizeChanged
End Sub
Private Sub Window_SizeChanged(sender As Object, e As SizeChangedEventArgs)
XAnimation.[To] = MarqueeContainer.ActualWidth * -1
MarqueeContainer.Visibility = Visibility.Hidden
SBMarquee.Begin()
MarqueeContainer.Visibility = Visibility.Visible
End Sub
End Class
Cool.
I'm not familiar with partial classes, but a quick check online seemed to suggest to me that I could just include the relevant parts into my VB class for the main window.
I don't know if the "initializeComponent" part is required, but it didn't throw an error. However, the attempt to create a Storyboard object met with some resistance. I figured that I needed an "Imports" command to get the proper namespace added (full disclosure: the idea of "namespaces" isn't obvious to me, but I get that something needed to be imported... the "namespace" moniker doesn't seem to fit, and I'm too literal). Here is what I added, right at the very top (above the "class" line):
Imports System.Windows.Media.Animation
Now these lines works:
Private story_OnAirUp As Storyboard
Private timeline_OnAirUp As DoubleAnimationUsingKeyFrames
The first line creates a Storyboard object, and the second makes the necessary timeline object. I thought at first I would be making an "EasingDoubleKeyFrame" object, which I could have made, but the child object of the Storyboard object is not a keyframe (well, not with the XAML constructed using the DoubleAnimationUsingKeyFrames element); my initial attempts to use a keyframe met with resistance. Here is what I tried which didn't work:
Private story_OnAirUp As Storyboard
Private keyframe_OnAirUp As EasingDoubleKeyFrame
No errors at this point, so I thought I was golden. Not so fast, young padawan.
Here is the next code I added, altered from the marquee example:
Private Sub Window_ContentRendered(sender As Object, e As EventArgs)
story_OnAirUp = TryCast(Me.Resources("story_OnAirUp"), Storyboard)
keyframe_OnAirUp = TryCast(story_OnAirUp.Children(1), EasingDoubleKeyFrame)
keyframe_OnAirUp.Value = grid_Top.ActualHeight / 2
AddHandler Me.SizeChanged, AddressOf MainWindow_SizeChanged
End Sub
No dice. The "TryCast(story_OnAirUp.Children(1)" part generates an error:
"Value of type 'Timeline' cannot be converted to 'EasingDoubleKeyFrame'."
Well, that stinks.
After some more comparison of the code, I see that my XAML code differs from the marquee example because of the inclusion of this line:
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid_OnAir">
So, the child of the Storyboard object isn't the EasingDoubleKeyFrame (well, not directly), but rather is the "DoubleAnimationUsingKeyFrames" element. However, the value I need to bind to isn't in the DoubleAnimationUsingKeyFrames element; it is in the EasingDoubleKeyFrame.
(Note: the sample code had "DoubleAnimation" the altered property as "To:" but the "EasingDoubleKeyFrame" uses the "value" property; I noticed that and adjusted accordingly.)
I tried to make a child object of the DoubleAnimationUsingKeyFrames element, but turns out "children" is a property of it. Then it dawned on me:
timeline_OnAirUp.KeyFrames(1).Value = grid_Top.ActualHeight / 2
The "(1)" points to the second keyframe, which is the one where the "On Air" grid is at the "full height," which has a default value of 84 pixels, but needs to change.
After I got the "Window_ContentRendered" done, I tried running the code.
Error in the "MainWindow_SizeChanged" subroutine:
"An unhandled exception of type 'System.NullReferenceException' occurred in WpfApplication3.exe
Additional information: Object reference not set to an instance of an object."
Hmmm. Okay, the "MainWindow_SizeChanged" routine is running before the "Window_ContentRendered" routine, not allowing the objects to be instantiated before they were used.
I moved the object creation code from "Window_ContentRendered" to "MainWindow_SizeChanged," remarked our the "ContentRendered" routine, and then tried again.
It worked. Here's the code which works:
XAML
<Window x:Name="SmartClock" x:Class="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:WpfApplication3"
xmlns:System="clr-namespace:System;assembly=mscorlib"
mc:Ignorable="d"
Title="MainWindow" Height="600" Width="800">
<Window.Resources>
<!-- Simple keyframe animation, which slides a bar with text into view -->
<Storyboard x:Key="story_OnAirUp" x:Name="OnAirUp">
<DoubleAnimationUsingKeyFrames Storyboard.TargetProperty="(FrameworkElement.Height)" Storyboard.TargetName="grid_OnAir">
<EasingDoubleKeyFrame KeyTime="0" Value="0"/>
<!-- **** This is the keyframe which has a changed value from the VB code -->
<EasingDoubleKeyFrame KeyTime="0:0:0.6" Value="84"/>
</DoubleAnimationUsingKeyFrames>
</Storyboard>
</Window.Resources>
<!-- Animation is triggered by clicking the button -->
<Window.Triggers>
<EventTrigger RoutedEvent="ButtonBase.Click" SourceName="button1">
<BeginStoryboard Storyboard="{StaticResource story_OnAirUp}"/>
</EventTrigger>
</Window.Triggers>
<!-- Here we setup the page -->
<Grid x:Name="grid_Page" ShowGridLines="True" >
<Grid.RowDefinitions>
<RowDefinition Height="3*"/>
<RowDefinition Height="4*"/>
<RowDefinition Height="3*"/>
</Grid.RowDefinitions>
<!-- This is "status" grid at the top of the page -->
<Grid x:Name="grid_Top" Grid.Row="0" d:LayoutOverrides="LeftMargin, RightMargin, TopMargin, BottomMargin" ShowGridLines="True" >
<Grid.RowDefinitions>
<RowDefinition Name="row_ProgramName"/>
<RowDefinition Name="row_Status" Height="Auto"/>
</Grid.RowDefinitions>
<Viewbox x:Name="viewbox_ProgramName" Grid.Row=" 0" Margin="0" Stretch="Uniform">
<TextBlock x:Name="textblock_ProgramName" Text="Some text on top" Background="#FFFFFF12"/>
</Viewbox>
<!-- This creates a grid which will hold the "ON AIR" bar -->
<Grid x:Name="grid_OnAir" Grid.Row="1" VerticalAlignment="Bottom" ShowGridLines="True" Height="84" >
<Rectangle x:Name="rectangle_OnAir" Fill="#FF90A436" RadiusX="20" RadiusY="20" Margin="10,0" Height="83"/>
<Viewbox x:Name="viewbox_OnAir" Grid.Row="1" Margin="0" Stretch="Uniform">
<TextBlock x:Name="textblock_OnAir" Text="ON AIR" FontSize="64" VerticalAlignment="Top" FontWeight="Bold" Background="#FFDC0000" Margin="0" HorizontalAlignment="Center" />
</Viewbox>
</Grid>
</Grid>
<!-- This is a big ugly button for triggering the storyboard -->
<Button x:Name="button1" Content="Button" Margin="0" Grid.Row="1" FontSize="26.667" HorizontalAlignment="Left" Width="257"/>
</Grid>
</Window>
VB
Imports System.Windows.Media.Animation
Class MainWindow
Public Sub New()
InitializeComponent()
End Sub
Private story_OnAirUp As Storyboard
Private timeline_OnAirUp As DoubleAnimationUsingKeyFrames
Private Sub MainWindow_SizeChanged(sender As Object, e As SizeChangedEventArgs) Handles Me.SizeChanged
' These next three lines were moved from the "ContentRendered" section
story_OnAirUp = TryCast(Me.Resources("story_OnAirUp"), Storyboard)
timeline_OnAirUp = TryCast(story_OnAirUp.Children(0), DoubleAnimationUsingKeyFrames)
timeline_OnAirUp.KeyFrames(1).Value = grid_Top.ActualHeight / 2
rectangle_OnAir.Height = grid_Top.ActualHeight / 2
viewbox_OnAir.Height = grid_Top.ActualHeight / 2
grid_OnAir.Height = grid_Top.ActualHeight / 2
' This is the line which actually sets the value to the animation keyframe.
timeline_OnAirUp.KeyFrames(1).Value = grid_Top.ActualHeight / 2
End Sub
End Class
Thanks for pointing me in the right direction, and I hope my follow-up (admittedly long) helps someone else.

How to Prompt Window on Image MouseDown

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 :)

SurfaceScrollViewer: getting touch on nested children

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.

How to make a windows slide out using WPF( expression Blend 4and C#)

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.

WPF 3.5 WebBrowser control and ZIndex

I'm trying to figure out why the control does not honor ZIndex.
Example 1 - which works fine
<Canvas>
<Rectangle Canvas.ZIndex="1" Height="400" Width="600" Fill="Yellow"/>
<Rectangle Canvas.ZIndex="2" Height="100" Width="100" Fill="Red"/>
</Canvas>
Example 2 - which does not work
<Canvas>
<WebBrowser Canvas.ZIndex="1" Height="400" Width="600" Source="http://www.stackoverflow.com"/>
<Rectangle Canvas.ZIndex="2" Height="100" Width="100" Fill="Red"/>
</Canvas>
Thanks,
-- Ed
Unfortunately this is because the WebBrowser control is a wrapper around the Internet Explorer COM control. This means that it gets its own HWND and does not allow WPF to draw anything over it. It has the same restrictions as hosting any other Win32 or WinForms control in WPF.
MSDN has more information about WPF/Win32 interop.
You are running into a common WPF pitfall, most commonly called the "The Airspace Problem". A possible solution is to NOT use the WebBrowser control, and instead go for something a little crazier - namely an embedded WebKit browser rendering directly to WPF. There are two packages that do this; Awesomonium (commercial) and Berkelium (open-source). There's a .NET wrapper for both of these.
You could SetWindowRgn to fake the overlapping area by hiding it as shown here:
flounder.com
msdn
I solved a similar issue where I was hosting a 3rd party WinForms control in my WPF application. I created a WPF control that renders the WinForms control in memory and then paints it to a bitmap. Then I use DrawImage in the OnRender method to draw the rendered content. Finally I routed mouse events from my control to the hosted control. In the case of a web browser you would also have to route keyboard events.
My case was fairly easy - a chart with some simple mouse interaction. A web browser control may have other issues that I didn't take into consideration. Anyway I hope that helps.
I hit this issue as well. In my case I was dragging images from one panel into the WebBrowser, but of course as soon as my image moved into the browser it was hidden.
Currently working on the following solution:
When the Image drag starts, create a Bitmap of the WebBrowser using "RenderTargetBitmap"
Add your Bitmap to the canvas, using the same width/location as the webbrowser
webControl.Visibility = Visibility.Hidden.
When the drag is released, remove your bitmap and set webControl.Visibility = Visible.
This solution is very specific to my situation, but maybe it will give you some ideas.
I managed to solve this by using this structure, check out the properties configuration in each element:
<Canvas ClipToBounds="False">
<Popup AllowsTransparency="True" ClipToBounds="False" IsOpen="True">
<Expander>
<Grid x:Name="YourContent"/>
</Expander>
<Popup>
</Canvas>
You just have to manage the Expander to show or hide your content, I'm using it for a menu bar, I think that the expander is optional depending on the case.
Check out this picture with the result, you can even show your controls on top of the WebBrowser and even outside the main window:

Resources