Creating UI element when user clicks in wpf - c#

What I want to do is make it so when the user clicks the 'rectangle' shape it creates a white border around the box like so....
If the user clicks in an area where no rectangle is present then it deselects any selected rectangles. I'm assuming this may need some additional changes in the code, any suggestions are welcome!

I found a solution for you. Let me know if this works for you. If not I will try and modify it. It is basic, but not that hard to implement I believe.
Here is the XAML. Note you will have to do all the positioning of the rectangles and such yourself. This just selects and deselects with a black border.
<Grid Background="#00000000" MouseDown="Grid_MouseDown" >
<Border Visibility="Hidden" x:Name="border" BorderBrush="Black" BorderThickness="1" Margin="230,135,142,58">
</Border>
<Rectangle x:Name="rect" Fill="Blue" MouseDown="Rectangle_MouseDown" Margin="250,148,160,74"/>
</Grid>
And here is the code behind.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Rectangle_MouseDown(object sender, MouseButtonEventArgs e)
{
border.Visibility = Visibility.Visible;
}
private void Grid_MouseDown(object sender, MouseButtonEventArgs e)
{
if (e.MouseDevice.DirectlyOver == rect)
{
}
else
{
border.Visibility = Visibility.Hidden;
}
}
}

Related

WPF Canvas Panning and Zoom

I've created an application that can read an XML file and display the rail network specified within a WPF Canvas.
I've been struggling for a while (months) to get the following functionality working and looking for any clue on how to proceed:
Zoom using mousewheel (zooming in makes the icons and tracks bigger whilst zooming out can let me see all the network).
Panning - Using the middle mouse button to drag the view screen.
I ended up having to disable the mouse wheel as it just moved the scrollviewer. In order for me to scroll currently, I have to use the scrollbar arrows.
Usually I would upload code samples but I've also uploaded everything to GitHub with everything needed in case you need to dive into the code or compile.
https://github.com/Legolash2o/NMViewer
XAML
<ScrollViewer x:Name="svCanvas" Grid.Row="2" HorizontalScrollBarVisibility="Visible" VerticalScrollBarVisibility="Visible" MouseMove="CCanvas_OnMouseMove" PreviewMouseWheel="SvCanvas_OnPreviewMouseWheel" MouseWheel="SvCanvas_OnPreviewMouseWheel" MouseDown="SvCanvas_OnMouseDown">
<Canvas x:Name="cMain" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Width="36000" Height="58000" >
<Canvas.RenderTransform>
<ScaleTransform x:Name="st"/>
</Canvas.RenderTransform>
</Canvas>
</ScrollViewer>
C#
private void SvCanvas_OnPreviewMouseWheel(object sender, MouseWheelEventArgs e)
{
e.Handled = true;
}
private void SvCanvas_OnMouseDown(object sender, MouseButtonEventArgs e)
{
if (e.MiddleButton == MouseButtonState.Pressed)
{
st.ScaleX = 1;
st.ScaleY = 1;
}
}
private void CCanvas_OnMouseMove(object sender, MouseEventArgs e)
{
if (drawing)
return;
lblBar.Content =
$"H[{svCanvas.HorizontalOffset}, V{svCanvas.VerticalOffset}] Mouse: {Mouse.GetPosition(cMain)}";
}

How To Let A Grid Capture The Mouse, But Still Allow It's Children To Handle Click Events

Sorry in advance if the title is confusing. Here's the situation. I have a grid called grdFilters. This grid has a series of CheckBoxes within it (one per row). Normally this grid is hidden. But I wanted it to show up when prompted (on button click) and leave when the user clicks somewhere other than the grid. To handle outside control mouse clicks I tried first capturing the mouse as such:
AddHandler(Mouse.PreviewMouseDownOutsideCapturedElementEvent, new MouseButtonEventHandler(HandleClickOutsideOfControl));
private void HandleClickOutsideOfControl(object sender, MouseButtonEventArgs e)
{
if (this.filters) //Check if the Filters grid is visible
{
ShowHideMenu("sbHideFilters", grdFilters); //Method that hides the grid
Mouse.Capture(null); //Release the mouse
}
}
private void btnFilters_Click(object sender, RoutedEventArgs e)
{
if (!this.filters) //Check if the filters grid is shown
{
ShowHideMenu("sbShowFilters", grdFilters); //Method that reveals the grid
Mouse.Capture(grdFilters); //Capture the mouse
}
}
The problem is that while the Filters grid has captured the mouse, none of the grids children (the Check Boxes) can be clicked on. I would really like to find a way to detect when the mouse is clicked outside of the grid while still allowing the children of the grid to accept mouse down events. Any help would be greatly appreciated, thanks in advance.
As per request here is some of my Xaml:
<Grid>
<Label x:Name="label" Content="Events" HorizontalAlignment="Center" VerticalAlignment="Top"/>
<ScrollViewer HorizontalAlignment="Left" Height="619" Margin="0,26,0,0" VerticalAlignment="Top" Width="450" VerticalScrollBarVisibility="Hidden">
<Grid x:Name="Schedule" HorizontalAlignment="Left" Height="Auto" VerticalAlignment="Top" Width="450" Margin="10,0,0,0"/>
</ScrollViewer>
<Grid x:Name="grdFilters" HorizontalAlignment="Left" Height="619" Margin="490,26,-176,0" VerticalAlignment="Top" Width="135" Background="{StaticResource TransparentBackground}" Panel.ZIndex="95">
<CheckBox x:Name="chckAll" Content="All" HorizontalAlignment="Left" Margin="0,10,0,0" VerticalAlignment="Top" Checked="chckAll_Checked" Unchecked="chckAll_Unchecked"/>
<Grid x:Name="grdFilters" HorizontalAlignment="Left" Height="588" Margin="0,31,0,0" VerticalAlignment="Top" Width="136"/>
</Grid>
<Button x:Name="btnFilters" Content="" Margin="436,223,-18,0" VerticalAlignment="Top" Background="Cyan" Opacity="0.15" Style="{StaticResource MyTabStyle}" Height="80" Click="btnFilters_Click"/>
</Grid>
The only thing I left out were the Resource Dictionaries and the page definition itself.
I think the Mouse.Capture and PreviewMouseDownOutsideCapturedElementEvent and are too specific for what you want.
I would rather use a hitResultsList, which can be used in a lot of different scenarios:
I slightly modified eh AddHandler
AddHandler(Mouse.PreviewMouseDownEvent, new MouseButtonEventHandler(HandleMouseDown));
And I added the VisualTreeHelper.HitTest logic
//List to store all the elements under the cursor
private List<DependencyObject> hitResultsList = new List<DependencyObject>();
private void HandleMouseDown(object sender, MouseButtonEventArgs e)
{
Point pt = e.GetPosition((UIElement)sender);
hitResultsList.Clear();
//Retrieving all the elements under the cursor
VisualTreeHelper.HitTest(this, null,
new HitTestResultCallback(MyHitTestResult),
new PointHitTestParameters(pt));
//Testing if the grdFilters is under the cursor
if (!hitResultsList.Contains(this.grdFilters) && grdFilters.Visibility == System.Windows.Visibility.Visible)
{
grdFilters.Visibility = System.Windows.Visibility.Hidden;
}
}
//Necessary callback function
private HitTestResultBehavior MyHitTestResult(HitTestResult result)
{
hitResultsList.Add(result.VisualHit);
return HitTestResultBehavior.Continue;
}
that way you can also remove the Mouse.Capture call from the btnFilters_Click:
private void btnFilters_Click(object sender, RoutedEventArgs e)
{
if (grdFilters.Visibility != System.Windows.Visibility.Visible)
grdFilters.Visibility = System.Windows.Visibility.Visible; }
}

WPF: Focus border after click

I'm trying to get my border focused after the user clicks on it.
Currently it is possible to focus the border via tabs, but via click would be way more convenient for the user.
<Border x:Name="BorderFileInfo" Focusable="True" BorderBrush="LightGray" BorderThickness="1">
<Grid Margin="3,0,0,0" VerticalAlignment="Center" HorizontalAlignment="Left">
<!-- CONTENT CTRL -->
</Grid>
</Border>
I saw in another post that there is a possability to catch the click event with an InputBinding but I don't know how to focus the border afterwards without using a command.
Stackoverflow: Why doesnt WPF border control have a mousedoubleclick event?
Is there an easy way to do that other than having to create commands ?
The app is pretty small so I don't want to use commands if I don't have to.
One easy way is to handle PreviewMouseDown or similar mouse events and set the focus:
private void Border_PreviewMouseDown(object sender, MouseButtonEventArgs e)
{
Keyboard.Focus(sender as Border);
}
edit
note that you can create Click by handling PreviewMouseLeftButtonDown and PreviewMouseLeftButtonUp in this way:
_isdown =false;
private void Border_PreviewMouseLeftButtonDown(object sender, MouseButtonEventArgs e)
{
_isdown =true;
}
private void Border_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
{
if ( _isdown)
{
_isdown = false;
Keyboard.Focus(sender as Border);
}
}

WPF: Opacity and the MouseEnter Event

As part of a diagram, I am drawing a few overlapping Shapes, each with Opacity=0.5, like here:
<Grid>
<Rectangle Fill="Blue" Opacity="0.5" MouseEnter="Rectangle_MouseEnter" />
<Rectangle Fill="Red" Opacity="0.5" />
</Grid>
private void Rectangle_MouseEnter(object sender, MouseEventArgs e)
{
MessageBox.Show("Entered");
}
When the user enters the shape with the mouse, some additional information should be displayed, but the event handler never gets called.
Is there a way to get MouseEnter events for all Shapes, instead of just the topmost one?
With your layout only the topmost rectangle will raise MouseEnter event. It fully overlaps the first rectangle.
Try this code for eventHandler:
private void Rectangle_MouseEnter(object sender, MouseEventArgs e)
{
if (sender != grid.Children[0])
{
var rect = (grid.Children[0] as Rectangle);
if (rect != null) rect.RaiseEvent(e);
}
else
{
MessageBox.Show("Entered.");
}
}
For this works you need to subscribe both rectangles to Rectangle_MouseEnter.

Add animation when user control get visible and collapsed In Wpf

I have two xaml files MainWindow.xaml and other user control WorkDetail.xaml file.
MainWindow.xaml file has a textbox, button, listbox and reference to WorkDetail.xaml(user control which is collapsed). Whenever user enter any text, it gets added in listbox when the add button is clicked. When any items from the listbox is double clicked, the visibility of WorkDetail.xaml is set to Visible and it gets displayed. In WorkDetail.xaml (user control) it has textblock and button. The Textblock displays the text of selected item and close button sets the visibility of WorkDetail window to collapsed. Now i am trying to animate WorkDetail.xaml when it gets visible and collapse. When any items from listbox is double clicked and WorkDetail.xaml visibility is set to visible, i want to create an animation of moving WorkDetail.xaml window from right to left on MainWindow. When Close button from WorkDetail.xaml file is clicked and WorkDetail.xaml file is collapsed, i want to slide the WorkDetail.xaml file from left to right from MainWindow.
Here is the screenshot:
MainWindow.xaml code:
<Window...>
<Grid Background="Black" >
<TextBox x:Name="enteredWork" Height="39" Margin="44,48,49,0" TextWrapping="Wrap" VerticalAlignment="Top"/>
<ListBox x:Name="workListBox" Margin="26,155,38,45" FontSize="29.333" MouseDoubleClick="workListBox_MouseDoubleClick"/>
<Button x:Name="addWork" Content="Add" Height="34" Margin="71,103,120,0" VerticalAlignment="Top" Click="Button_Click"/>
<TestWpf:WorkDetail x:Name="WorkDetail" Visibility="Collapsed"/>
</Grid>
</Window>
MainWindow.xaml.cs class code:
namespace TestWpf
{
public partial class MainWindow : Window
{
public MainWindow()
{
this.InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
workListBox.Items.Add(enteredWork.Text);
}
private void workListBox_MouseDoubleClick(object sender, MouseButtonEventArgs e)
{
WorkDetail.workTextBlk.Text = (string)workListBox.SelectedItem;
WorkDetail.Visibility = Visibility.Visible;
}
}
}
WorkDetail.xaml code:
<UserControl ..>
<Grid Background="#FFD2CFCF">
<TextBlock x:Name="workTextBlk" Height="154" Margin="33,50,49,0" TextWrapping="Wrap" VerticalAlignment="Top" FontSize="29.333" Background="#FFF13939"/>
<Button x:Name="btnClose" Content="Close" Height="62" Margin="70,0,94,87" VerticalAlignment="Bottom" Click="btnClose_Click"/>
</Grid>
</UserControl>
WorkDetail.xaml.cs class code:
namespace TestWpf
{
public partial class WorkDetail : UserControl
{
public WorkDetail()
{
this.InitializeComponent();
}
private void btnClose_Click(object sender, System.Windows.RoutedEventArgs e)
{
Visibility = Visibility.Collapsed;
}
}
}
Can anyone tell how can i do this?
is this link interesting for you? I think that something very similar is accomplished using a VisualBrush based technique. It's worth a look!
JAPF http://www.remote-screenshots.com/thumbs/medium/0/www.japf.fr.jpg
Another idea would be using the VisualStateManager and Transistions: You can overwrite the style information of your controls and use Storyboard animations - without tools like Blend this could become very tricky, though.
Hope that helps anyway.
best regards,
thomas

Categories