WPF - C# Put a label over a PictureBox (using windowsformhost) - c#

I am currently developping an interface that shows multiple camera shot and the direct view of the camera.
What i need to do is put a label on a picturebox (picturebox that refresh camera live every frame).
My problem is that when the picturebox refresh, the label get under it.
Here's how my XAML code is made :
<Grid x:Name="GridCam4" Grid.Column="1" Grid.Row="1" Margin="0,0,24,0">
<WindowsFormsHost x:Name="DisplayWindow" Foreground="#FFA0A0A0" Background="#FFA0A0A0" Panel.ZIndex="2" Height="435" Width="678">
<forms:PictureBox x:Name="picturebox1" BackgroundImageLayout="None"/>
</WindowsFormsHost>
<Label x:Name="LabelLive" Content="Live :" HorizontalAlignment="Left" Margin="10,10,0,0" VerticalAlignment="Top" Height="102" Width="206" FontSize="36" Panel.ZIndex="12" Foreground="White"/>
</Grid>
And there is my C# code :
private void onFrameEvent(object sender, EventArgs e)
{
uEye.Camera Camera = sender as uEye.Camera;
Camera.Memory.GetLast(out s32MemID);
//Display the image on the screen (Refresh the picturebox with last picture taken)
Camera.Display.Render( DisplayHandle, uEye.Defines.DisplayRenderMode.FitToWindow);
Camera.Memory.Unlock(s32MemID);
this.Dispatcher.Invoke(
new Action(() =>
{
LabelLive.Content = "Live :"; //Trying to refresh the label to put it over picturebox
}),
DispatcherPriority.ApplicationIdle);
}
I really don't know what to do to deal with this...
I have also tried ZPanels but nothing worked at the moment.
Thanks for your help !

Related

How can I capture WPF events from a Winforms app

I have an WPF User control which is is hosted in an Elementhost. I use elementhost to include an WPF user control in my classical Windows forms app.
Now, from Windows forms side I am trying to capture the mouseDown event that is produced in an WPF label but I don't know how to do it.
Any ideas?
A case might be able to help you. The winform form calls the wpf control.
Create a WPF custom control. The xaml code of the control is as follows.
<Grid>
<Image Margin="10,10,10,90" x:Name="img" Stretch="Uniform" Opacity="1">
<Image.BitmapEffect>
<DropShadowBitmapEffect Opacity="1" />
</Image.BitmapEffect>
</Image>
<TextBox Background="Transparent" Foreground="White" Height="40" FontSize="32" Margin="44,0,56,36" x:Name="txtBox1" Opacity="0.5" Text="" VerticalAlignment="Bottom" /> </Grid>
You need to add the corresponding function to set the effect. The code is as follows.
public void SetSource(string fileName)
{
img.Source = new BitmapImage(new Uri(fileName) );
}
public void SetOpacity(double opacity)
{
img.Opacity = opacity;
}
//
public string GetText()
{
return txtBox1.Text;
}
Create a Winform application and add a reference, otherwise the control will not work properly. The list of references is pictured below.
Regenerate the solution. On the left toolbar, a WPF control appears and drag it to the form.
Use the button control in the winform project to call the corresponding function.
private void button1_Click(object sender, EventArgs e)
{
((UserControl1)elementHost1.Child).SetSource(#"C:\Users\Admin\Pictures\Saved Pictures\9837f99502eba3d01d4fb671cab20c15.jpg");
}
private void button2_Click(object sender, EventArgs e)
{
((UserControl1)elementHost1.Child).SetOpacity(0.5);
}
private void button3_Click(object sender, EventArgs e)
{
string text = ((UserControl1)elementHost1.Child).GetText();
label1.Text = text;
}
Test items: The left side is the traditional Winform control. The right side is the imported WPF control. You can clearly see the "translucent" effect of the picture.
Not sure what exactly you're trying to achieve. Below is a simple example.You can edit the MouseDown event of the UserControl as needed.
If there is a problem, please make your problem clearer and show me the complete code sample that can reproduce your problem for analysis.
UserControl:
<Grid>
<Label x:Name="label" Content="Label" MouseDown="label_MouseDown" Background="AliceBlue" Width="300" Height="200" />
</Grid>
private void label_MouseDown(object sender, MouseButtonEventArgs e)
{
MessageBox.Show("hello");
}
Add the UserControl reference in the WinForms project, drag and drop the UserControl on the Form1 designer after rebuilding the WinForms project.
The result of running the project and clicking the Label in the UserControl is shown in the figure.

Place button right after 1-2 line text ends

There are pictures of what I want to achieve in this question.
I tried putting the TextBlock and the Button in a WrapPanel, and this works for single-line text but not for multi-line text.
<WrapPanel>
<TextBlock
TextTrimming="WordEllipsis"
TextWrapping="WrapWithOverflow" .../>
<Button .../>
</WrapPanel>
The picture below shows what's happening. When the TextBlock text becomes 2 lines the second line takes the whole width of the first line, which is logical.
I thought of chopping the string by words and using an ItemsControl with WrapPanel as ItemsPanel. But the text may become longer, and there isn't space for more than 2 lines, that's why I put the TextTrimming="WordEllipsis" there; the remaining text will be trimmed and the button will be at the end of the second line, in that case.
Update: Well it turned out to be not so easy, I went with changing my UI to something simpler like putting a rounded button on the right.
If you don't mind to use TextBox insteaf of TextBlock, it has TextBox.GetRectFromCharacterIndex method to get the rectangle of character by index number and you can utilize it to adjust the position of Button accordingly.
The following is just a proof of concept and there is much room to modify.
Xaml:
<Grid Width="200" Height="100">
<TextBox x:Name="textBox"
TextWrapping="WrapWithOverflow" AcceptsReturn="True"
TextChanged="TextBox_TextChanged"/>
<Button x:Name="button"
HorizontalAlignment="Left" VerticalAlignment="Top"
Content="END" Padding="0" VerticalContentAlignment="Center"/>
</Grid>
Code behind:
private void TextBox_TextChanged(object sender, TextChangedEventArgs e)
{
AdjustButtonPosition();
}
private void AdjustButtonPosition()
{
if (this.textBox is null || this.button is null)
return;
var index = textBox.Text.Length;
var rect = textBox.GetRectFromCharacterIndex(index);
button.Margin = new Thickness(rect.Right, rect.Top, 0, 0);
button.Height = rect.Height;
}

Why is my Named WPF Shape Inaccesible from Code Behind?

I have an Ellipse in my WPF application. I want to change the colour of its outline whenever it is double clicked. I found this (old) tutorial about making this work by using the available MouseDown event and checking for a ClickCount of two in the event handler. This is the simplest solution to my problem and I'd like to try and get this to work before creating an empty button Control Template.
However, I'm unable to find the clicked ellipse in my code behind file. Supposedly this works in the tutorial, but I'm wondering if I'm missing anything.
Here's the code that contains the ellipse. It is the 3rd column of a grid:
<ScrollViewer VerticalScrollBarVisibility="Auto" HorizontalScrollBarVisibility="Auto" Grid.Column="3">
<StackPanel Orientation="Vertical" Margin="3,1" Background="GhostWhite">
<ItemsControl Name="FlowLinkItems" ItemsSource="{Binding FlowLinkList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<Grid Height="40">
<Ellipse Name="FlowLinkEllipse" Stroke="BlueViolet" Height="38" VerticalAlignment="Center" MouseDown="Ellipse_MouseDown"/>
<TextBlock TextAlignment="Center" HorizontalAlignment="Center" VerticalAlignment="Center" Text="{Binding Message}"></TextBlock>
</Grid>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
</StackPanel>
</ScrollViewer>
In the tutorial, the code behind method worked like this:
private void Ellipse_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.ClickCount == 2)
{
FlowLinkEllipse.Stroke = "Red";
}
}
And the error I'm seeing is:
The name 'FlowLinkEllipse' does not exist in the current context
If this method is not possible I'm open to suggestions that are as simple as possible (I'm still new to WPF and the only thing my app will handle is this double click).
Note: I do have this line in my code behind and it works fine.
FlowLinkItems.MouseLeftButtonUp += FlowLinkItems_MouseLeftButtonUp;
As #Magus noted, you can't reference an item from code-behind, that is inside a DataTemplate. That should be no problem here, though: sender will contain a reference to the ellipse:
private void Ellipse_MouseDown(object sender, MouseButtonEventArgs e)
{
if (ellipse as sender == null || e.ClickCount < 2)
return;
var ellipse = (Ellipse)sender;
ellipse.Stroke = System.Windows.Media.Brushes.Red;
}

Button with image blue background

I create a button with image in my app:
<Button x:Name="favoriteButton" HorizontalAlignment="Left" VerticalAlignment="Top" Height="72" Width="99" Click="DidPressAddToFavorites" BorderBrush="{x:Null}" Foreground="{x:Null}">
<Button.Background>
<ImageBrush ImageSource="/Images/favouritesBWIcon#2x.png" Stretch="Uniform"/>
</Button.Background>
</Button>
And i noticed that when the user press the button all the button became blue and when i release the button i see it again. any idea how to fix it?
Edit:
This is the handler method:
private void DidPressAddToFavorites(object sender, RoutedEventArgs e)
{
if (favoriteRep.ExistInFavorites(currentItem) == true)
{
this.SetButtonWithImage(favoriteButton, "/Images/favouritesBWIcon#2x.png");
favoriteRep.RemoveFromFavorites(currentItem);
}
else
{
this.SetButtonWithImage(favoriteButton, "/Images/favouritesIcon#2x.png");
favoriteRep.AddToFavorites(currentItem);
}
}
Because you didn't add the States, there are three states Normal, MouseOver, Pressed... You have to set the image for all three states, to make it work of your wish. Here the alternate to do so, didn't know about any better way available from c#, all you have to do is to add two more eventHndlers Mouse over event and press event, then set the image in both of them....
Well there's another good way to do so is try template editing from blend Software

Getting events from the scrollbar buttons?

how can I access the arrow buttons on the ends of scrollbars in silverlight? Are they button controls which can be accessesed through thescrollbar class or something else?
The reason I need to know this is so that when someone click on either of the arrow buttons I can run some custom functionality to the scrollbar
If you need to know what button of the scrollbar was clicked you can could access that via the ValueChanged property of the ScrollBar
For instance I've got a simple scroll bar with a textblock and on each click, the textblock displays which button was clicked.
<Grid x:Name="LayoutRoot" Background="White">
<ScrollBar Height="200" Orientation="Vertical" Width="20" ValueChanged="ScrollBar_ValueChanged" />
<TextBlock Height="23" HorizontalAlignment="Left" Margin="150,21,0,0" Name="textBlock1" Text="" Width="100" VerticalAlignment="Top" />
</Grid>
and the code behind would be
private void ScrollBar_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
{
if (e.NewValue > e.OldValue)
textBlock1.Text = "Down Arrow Clicked";
else
textBlock1.Text = "Up Arrow Clicked";
}
Solved this problem like so:
foreach( var o in horizontalBar.GetVisualDescendants( ) )
{
if(o is RepeatButton)
{
//set call back based on the name of the repeatbutton
}
}

Categories