I'm working with WPF Popup. A popup contains some keyboard.
I want to open a popup when a user clicks on a text box and do not hide a popup while textbox has the focus.
Also I need to hide a popup when a user clicks somewhere away from a popup.
Here's the xaml code:
<Grid>
<StackPanel>
<TextBox x:Name="textBox" GotKeyboardFocus="textBox_GotFocus" MouseDown="textBox_MouseDown" />
<Popup x:Name="popup" Width="100" Height="100" PlacementTarget="{Binding ElementName=textBox}" Placement="Bottom"
StaysOpen="{Binding ElementName=text,Path=IsKeyboardFocused}">
<Grid Background="Blue">
</Grid>
</Popup>
</StackPanel>
</Grid>
Here's the c# code:
private void textBox_GotFocus(object sender, KeyboardFocusChangedEventArgs e)
{
popup.IsOpen = true;
}
private void textBox_MouseDown(object sender, MouseButtonEventArgs e)
{
popup.IsOpen = true;
}
I found that the binding can help:
StaysOpen="{Binding ElementName=,Path=IsKeyboardFocused}"
But the TextBox never hides. Also if I set StaysOpen="False" the TextBox never shows
You could handle the LostKeyboardFocus event and check whether the new focused element is the TextBox itself or if it's a child element of the Popup:
private void textBox_GotFocus(object sender, KeyboardFocusChangedEventArgs e)
{
popup.IsOpen = true;
}
private void textBox_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
var newFocusedElement = e.NewFocus as DependencyObject;
//if the focused element is a child of the window, it can't be the child of the popup
if (newFocusedElement == null || FindParent<Window>(newFocusedElement) != null)
popup.IsOpen = false;
}
private void popup_LostKeyboardFocus(object sender, KeyboardFocusChangedEventArgs e)
{
popup.IsOpen = e.NewFocus == textBox;
}
private static T FindParent<T>(DependencyObject dependencyObject) where T : DependencyObject
{
var parent = VisualTreeHelper.GetParent(dependencyObject);
if (parent == null) return null;
var parentT = parent as T;
return parentT ?? FindParent<T>(parent);
}
Sample XAML:
<StackPanel>
<TextBox x:Name="textBox" GotKeyboardFocus="textBox_GotFocus" LostKeyboardFocus="textBox_LostKeyboardFocus" />
<Popup x:Name="popup" Width="100" Height="100" PlacementTarget="{Binding ElementName=textBox}"
LostKeyboardFocus="popup_LostKeyboardFocus"
Placement="Bottom">
<Grid x:Name="popupRoot" Background="Blue">
<TextBox Margin="10" />
</Grid>
</Popup>
<TextBox />
</StackPanel>
Related
i have class created for data retrieval
I have XAML code with gridview and cs code which connects to SQL webservice and i can get data from SQL :-)
my gridview has
textblock - data from sql table
checkbox
textbox
I would like to have some actions on the checkbox and textboxes. How do I get my textboxes to become visible upon checkbox click?
I have got this code working in other apps without gridviews, but I can't get it to work here. how do I reference the event_handler inside the gridview
XAML example
<GridView x:Name="GreenQuestionGridView" ItemsSource="{Binding}" Background="Green" Margin="0,40,0,0">
<GridView.ItemTemplate>
<DataTemplate>
<Grid Height="40" Width="600" >
<StackPanel Orientation="Horizontal">
<TextBlock Width="200" VerticalAlignment="Bottom" TextWrapping="Wrap" Text="{Binding question_green}" />
<CheckBox x:Name="chkBox" Checked="chkBox_Checked" Unchecked="chkBox_Unchecked" Indeterminate="chkBox_Indeterminate" VerticalAlignment="Bottom" IsThreeState="True" />
<TextBox x:Name="txtBox" Visibility="Collapsed" Width="200" VerticalAlignment="Bottom" />
</StackPanel>
</Grid>
</DataTemplate>
</GridView.ItemTemplate>
</GridView>
here is code that works in other app, but this needs to reference the gridview
private void chkBox_Checked(object sender, RoutedEventArgs e)
{
if (chkbox.IsChecked == null)
{
txtbox.Visibility = Visibility.Visible;
}
else
{
txtbox.Visibility = Visibility.Collapsed;
}
}
For the CheckBox you need also the event CheckBox_Unchecked to hide it again.
<CheckBox Unchecked="CheckBox_Unchecked" Checked="CheckBox_Checked" ... />
IsChecked is a nullable type you didnt even checked if it's true. Your code will hide the txtbox so long as the IsChecked is not null.
private static void ToggleTextBoxVisibility(object sender) {
if(!(sender is CheckBox)) {
return;
}
CheckBox checkBox = sender as CheckBox;
foreach(var child in ((checkBox.Parent as StackPanel).Children)) {
if(!(child is TextBox)) {
continue;
}
TextBox textBox = child as TextBox;
if(checkBox.IsChecked.HasValue && checkBox.IsChecked.Value) {
textBox.Visibility = Visibility.Visible;
} else {
textBox.Visibility = Visibility.Collapsed;
}
}
}
private void CheckBox_Checked(object sender, RoutedEventArgs e) {
ToggleTextBoxVisibility(sender);
}
private void CheckBox_Unchecked(object sender, RoutedEventArgs e) {
ToggleTextBoxVisibility(sender);
}
A clean solution would be to control it with a binding to a property in your viewmodel.
I have 3 textbox. How can i know which one of them has the focus?
if (TextBoxExtendedSearchName.Focus() == false &&
TextBoxExtendedSearchNomenclature.Focus() == false
&& TextBoxExtendedSearchSpecialist.Focus() == false)
{
window.Close();
}
this does not work
I Use WPF
private void TextBox1_LostFocus(object sender, RoutedEventArgs e)
{
if (!TextBox1.IsFocused && !TextBox2.IsFocused)
MessageBox.Show("Not Focus");
}
private void TextBox2_LostFocus(object sender, RoutedEventArgs e)
{
if (!TextBox1.IsFocused && !TextBox2.IsFocused)
MessageBox.Show("Not Focus");
}
this example not work
I think I understand what the problem is. it does not work when I'm doing it in the event Lost Focus.
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void TextBox1_LostFocus(object sender, RoutedEventArgs e)
{
if (!TextBox1.IsFocused && !TextBox2.IsFocused)
MessageBox.Show("Not Focus");
else
MessageBox.Show("Yes Focus");
}
private void TextBox2_LostFocus(object sender, RoutedEventArgs e)
{
if (!TextBox1.IsFocused && !TextBox2.IsFocused)
MessageBox.Show("Not Focus");
else
MessageBox.Show("Yes Focus");
}
XAml
<Window x:Class="TrainWPF.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="MainWindow" Height="350" Width="525">
<Grid>
<TextBox x:Name="TextBox1" HorizontalAlignment="Left" Height="25" Margin="62,61,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="205" LostFocus="TextBox1_LostFocus"/>
<TextBox x:Name="TextBox2" HorizontalAlignment="Left" Height="23" Margin="62,145,0,0" TextWrapping="Wrap" Text="TextBox" VerticalAlignment="Top" Width="205" LostFocus="TextBox2_LostFocus"/>
<Button Content="Button" HorizontalAlignment="Left" Margin="267,249,0,0" VerticalAlignment="Top" Width="96" RenderTransformOrigin="0.5,0.5" Height="37">
<Button.RenderTransform>
<TransformGroup>
<ScaleTransform/>
<SkewTransform/>
<RotateTransform Angle="0.397"/>
<TranslateTransform/>
</TransformGroup>
</Button.RenderTransform>
</Button>
</Grid>
</Window>
this does not work
I understand it's my logical error
try this:
//Logical focus
var focusedControl = FocusManager.GetFocusedElement(this);
//KeyBoard focus
var focusedControl = Keyboard.FocusedElement;
// dummy logic to close the window when all the three textboxes are not focused.
List<TextBox> items=new List<TextBox>();
items.Add(TextBoxExtendedSearchName);
items.Add(TextBoxExtendedSearchNomenclature);
items.Add(TextBoxExtendedSearchSpecialist);
if(!items.Any(o=>o==focusedControl))
{
window.Close();
}
You are using the wrong function. You need to use the IsFocused property to get it a Control has a focus.
See the documentation here: Link
With your code:
if (!TextBoxExtendedSearchName.IsFocused
&& !TextBoxExtendedSearchNomenclature.IsFocused
&& !TextBoxExtendedSearchSpecialist.IsFocused)
{
window.Close();
}
This will Close the window if none of them has a Focus.
I want to make this as, once i select the first item(Student Information) of the first_ComboBox want to appear second_ComboBox.
How can I make this happen
In the cs code
private void first_ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
private void second_ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
}
in XAML
<StackPanel Margin="97,47,171,499" Orientation="Horizontal" Grid.Row="1">
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Where You want to Control" VerticalAlignment="Top" Height="82" Width="463" FontSize="36"/>
<ComboBox x:Name="first_ComboBox" HorizontalAlignment="Left" VerticalAlignment="Top" Width="560" Height="42" SelectionChanged="first_ComboBox_SelectionChanged">
<x:String>Student Information</x:String>
<x:String>Staff Information</x:String>
<x:String>Academic Information</x:String>
</ComboBox>
</StackPanel>
<StackPanel Margin="97,172,171,374" Orientation="Horizontal" Grid.Row="1">
<TextBlock HorizontalAlignment="Left" TextWrapping="Wrap" Text="Select the Field" VerticalAlignment="Top" Height="82" Width="463" FontSize="36"/>
<ComboBox x:Name="second_ComboBox" HorizontalAlignment="Left" VerticalAlignment="Top" Width="560" Height="42" SelectionChanged="second_ComboBox_SelectionChanged">
<x:String>Student Name</x:String>
<x:String>Student Address</x:String>
</ComboBox>
</StackPanel>
On your Form main, you can set the visibility of Second Combobox to be false, and then on the first combobox selection changed set it to true, Something like this
public MainWindow()
{
InitializeComponent();
second_ComboBox.Visibility = Visibility.Collapsed;
}
private void first_ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
var selecteditem = first_ComboBox.SelectedItem as string;
if (selecteditem != null)
{
second_ComboBox.Visibility = Visibility.Visible;
}
}
on initialization make second combobox visiblity hidden
public MainWindow()
{
InitializeComponent();
second_ComboBox.Visibility = Visibility.Collapsed;
}
private void first_ComboBox_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
first_ComboBox.Visibility = System.Windows.Visibility.Visible;
}
In WinRT (Windows Store Apps), I create a tooltip and set it to an element like this:
dragTip = new ToolTip();
dragTip.Content = "Test";
ToolTipService.SetToolTip(element as DependencyObject, dragTip);
dragTip.IsOpen = true;
I want to move this ToolTip as the mouse moves. Is there a way to do that? Or another alternative? I want to show a hint to the user as he/she drags an element.
Update
Here's the approach I took based on #Sajeetharan's suggestion:
<Grid Background="{StaticResource ApplicationPageBackgroundThemeBrush}" PointerMoved="homeGrid_PointerMoved" x:Name="homeGrid">
....
<GridView x:Name="content" CanDragItems="True" DragItemsStarting="content_DragItemsStarting">
...
</GridView>
<Popup Name="DeepZoomToolTip">
<Border CornerRadius="1" Padding="1" IsHitTestVisible="False">
<TextBlock Text="Here is a tool tip" />
</Border>
</Popup>
....
</Grid>
private void content_DragItemsStarting(object sender, DragItemsStartingEventArgs e)
{
DeepZoomToolTip.IsOpen = true;
}
private void homeGrid_PointerMoved(object sender, PointerRoutedEventArgs e)
{
var position = e.GetCurrentPoint(homeGrid).Position;
DeepZoomToolTip.HorizontalOffset = position.X;
DeepZoomToolTip.VerticalOffset = position.Y;
}
Notice that the tooltip will move but not when the item is being dragged.
You can do this by using a popup control , Here is the full Thread how to make tooltip move along with mouse
XAML:
<Canvas x:Name="LayoutRoot" Background="White">
<Image Source="/sam.png" MouseMove="Image_MouseMove" MouseLeave="Image_MouseLeave"/>
<Popup Name="DeepZoomToolTip">
<Border CornerRadius="1" Padding="1" IsHitTestVisible="False">
<TextBlock Text="Here is a tool tip" />
</Border>
</Popup>
</Canvas>
private void Image_MouseMove(object sender, MouseEventArgs e)
{
DeepZoomToolTip.IsOpen = true;
DeepZoomToolTip.HorizontalOffset = e.GetPosition(LayoutRoot).X;
DeepZoomToolTip.VerticalOffset = e.GetPosition(LayoutRoot).Y;
}
private void Image_MouseLeave(object sender, MouseEventArgs e)
{
DeepZoomToolTip.IsOpen = false;
}
I am trying to use context menu in a listbox to run some come code.that require data from which item it originated.the click event context menu item shows msg but i found that it doent not access the originating listview item .
<Canvas x:Name="LeftCanvas" Grid.Column="0" Grid.Row="1" Margin="5,0,0,0">
<StackPanel>
<TextBlock Text="Unseated Guests" Background="Blue" Foreground="White" FontFamily="Verdana" FontSize="11" FontWeight="Bold" Height="17" Width="150" HorizontalAlignment="Left" TextAlignment="Center" Padding="0,4,5,2"></TextBlock>
<ListBox x:Name="UnseatedPersons" ItemsSource="{Binding}" Height="218" Width="150" BorderBrush="Blue" BorderThickness="2" HorizontalAlignment="Left" Padding="3,2,2,2" src:FloorPlanClass.DragEnabled="true" MouseEnter="UnseatedPersons_MouseEnter"
MouseLeave="SourceListBox_MouseLeave">
<ListBox.ItemTemplate>
<DataTemplate>
<DockPanel>
<DockPanel.ContextMenu>
<ContextMenu>
<MenuItem Header="Archive Info" Click="bt_click" />
<MenuItem Header="Guest Info" />
</ContextMenu>
</DockPanel.ContextMenu>
<Image Name="imgPerson" Source="{Binding ImagePath}" />
<TextBlock Name="txtPersonName" Text="{Binding PersonName}" Padding="2,4,0,0" />
</DockPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</StackPanel>
</Canvas>
C#:
void bt_click(object sender, RoutedEventArgs e)
{
MessageBox.Show("my message");
}
Use the sender by casting them to MenuItem. Like:
void bt_click(object sender, RoutedEventArgs e)
{
MenuItem originalItem = (MenuItem)sender;
MessageBox.Show(string.Format("clicked from \"{0}\"", originalItem.Name));
}
The sender in the click event will be the MenuItem you clicked.
Its parent will be the ContextMenu
The PlacementTarget of the ContextMenu will be the DockPanel.
The DockPanel will have the ListBoxItem as an ancestor in the Visual Tree
So to get the ListBoxItem in the click event you can use something similar to this
private void bt_click(object sender, RoutedEventArgs e)
{
MenuItem clickedMenuItem = sender as MenuItem;
ContextMenu contextMenu = clickedMenuItem.Parent as ContextMenu;
DockPanel dockPanel = contextMenu.PlacementTarget as DockPanel;
ListBoxItem listBoxItem = GetVisualParent<ListBoxItem>(dockPanel);
MessageBox.Show(listBoxItem.ToString());
// Update. To display the content of the ListBoxItem
MessageBox.Show(listBoxItem.Content.ToString());
}
public static T GetVisualParent<T>(object childObject) where T : Visual
{
DependencyObject child = childObject as DependencyObject;
// iteratively traverse the visual tree
while ((child != null) && !(child is T))
{
child = VisualTreeHelper.GetParent(child);
}
return child as T;
}