Keep WPF popup window open after user has made choice - c#

I have a small pop up window coming up when user selects a record from the main grid. I would like to keep this window open after user has made the selection until he or she clicks cancel. Here is my little code. If I comment out this.close() method then control never returns back to execute rest of the code.
private void ClickSubmit(object sender, RoutedEventArgs e)
{
try
{
IsCancelled = false;
// Figure out to keep this little window open after clicking submit !!
this.Close();
return;
}
catch (Exception ex)
{
ex.ToString();
}
}
private void ClickCancel(object sender, RoutedEventArgs e)
{
try
{
Trace.WriteLine("Popup exit !");
IsCancelled = true;
this.Close();
return;
}
catch (Exception ex)
{
ex.ToString();
}
}
OrdRec or = lvOrders.SelectedItem as OrdRec;
PxQtyPopup pop = new PxQtyPopup(or);
//pop.ShowDialog();
pop.Show();
if (!pop.IsCancelled) // check whether price/qty change submitted or popup window was cancelled
(DCtxt as OrdViewModel).ModifyOrder(or, int.Parse(pop.Qty), decimal.Parse(pop.Px));

Bind the IsOpen to a suitable boolean which will instead open or close the popup. The below example uses a ToggleButton's OpenState (boolean) which will open/close the popup.
<ToggleButton Height="30" Width="60"
x:Name="OpenState">
<StackPanel>
<TextBlock Text="{Binding IsChecked, ElementName=OpenState}"
FontSize="18"
VerticalAlignment="Center"
HorizontalAlignment="Center">
</TextBlock>
<Popup Name="myPopup"
IsOpen="{Binding IsChecked, ElementName=OpenState}">
<TextBlock Name="myPopupText"
Background="LightBlue"
Foreground="Blue">Popup Text</TextBlock>
</Popup>
</StackPanel>
</ToggleButton>

Is your Popup a new WPF window? - You answered yes.
One way to do this would be to expose 2 events in your Popup window. ExitWithClose & ExitWithoutClose. Main window can handle these 2 events and do the after popup processing in the handlers.
Otherwise, prefer using WPF Popup control.
WPF Popup works with IsOpen property. Here's how to keep a popup open or close it.
You will see
Xaml:
<Grid Name="MainGrid">
<Button Height="20" Width="100" Click="Button_Click">Click Me!</Button>
<Popup Margin="10,10,0,13" Name="Popup1" HorizontalAlignment="Center" VerticalAlignment="Center"
PlacementTarget="{Binding MainGrid}" Placement="Center"
Width="194" Height="200">
<StackPanel Orientation="Vertical" Background="Gray">
<Button Height="20" Width="150" Click="Button_ClickToStayOpen" Margin="10">Don't Close Me!</Button>
<Button Height="20" Width="150" Click="Button_ClickToClose" Margin="10">Close Me!</Button>
</StackPanel>
</Popup>
</Grid>
Code behind:
private void Button_Click(object sender, RoutedEventArgs e)
{
//Show Popup
Popup1.IsOpen = true;
}
private void Button_ClickToStayOpen(object sender, RoutedEventArgs e)
{
// Do actions
//Keep Popup Open
}
private void Button_ClickToClose(object sender, RoutedEventArgs e)
{
//Close Popup
Popup1.IsOpen = false;
}
When the window opens there will be a Click Me button. When you click it, a popup will launch. Popup will have 2 buttons. One will help you do some action without closing popup. The other will close the popup.

Related

Modal dialog always misses first button tap after opening from double tap

I am displaying a modal dialog when the user double taps inside a TextBlock. Its a backdoor to a hidden settings panel. The TextBlock is contained in a Popup. I am finding that it is always necessary to tap/touch once before any of the buttons in the dialog do anything. Kind of annoying. Initially was using MouseLeftButtonDown and ClickCount==2 on the TextBlock but have also tried the DoubleClickEvent of a Label and their Preview... versions. Nothing I have tried fixes this problem.
<TextBlock Foreground="Black" FontSize="16" Grid.ColumnSpan="4" HorizontalAlignment="Center" MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" VerticalAlignment="Center" Padding="0,10,0,10">
<Run Text="{x:Static languages:Strings.SoftwareVersion}"/>
<Run Text="{Binding SoftwareBuild}"/>
<Run Text=" "/>
<Run Text="{x:Static languages:Strings.FirmwareVersion}"/>
<Run Text="{Binding FirmwareBuild}"/>
</TextBlock>
private void TextBlock_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
{
try
{
if (e.ClickCount == 2)
{
var sw = new SettingsWindow();
sw.WindowStartupLocation = System.Windows.WindowStartupLocation.CenterScreen;
sw.DataContext = this.DataContext;
sw.ShowDialog();
}
}
catch (Exception ex)
{
ex.HandleException();
}
}
I've made a correction to the title as the problem is only with touch/tap behaviour; the first mouse click does get through only the first touch fails.
Added more code for the SettingsWindow as requested:-
<Window x:Class="XXXXXXX.UserInterface.Views.Miscellaneous.SettingsWindow"
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"
mc:Ignorable="d"
Title="SettingsWindow" Height="150" Width="200">
<Grid>
<Button Content="Click Me" Click="Button_Click" VerticalAlignment="Center" HorizontalAlignment="Center" Height="48" Margin="50,30,37,41" Width="105" />
</Grid>
</Window>
public partial class SettingsWindow : Window
{
public SettingsWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
(sender as Button).Background = new SolidColorBrush(Colors.Red);
(sender as Button).Content = "WAS CLICKED";
}
}
Ive tried focus setting in the load and activate event of the dialog to no avail. Even tried raising a MouseClick event using RaiseEvent.
Same problem if I only count 1 click too but with 1 click the problem goes away if I count MouseButtonUp events not MouseButtonDown, but then I lose the ClickCount==2 option which doesnt work at all. Somewhere a MouseButtonUp event is getting lost.
So I'm about to manage my own double clicking to get this to work ...
but suggestions welcome as to why this breaks.
Jerry

UWP: TextBox inside Button, how to prevent SpaceBar from triggering the Click event?

i want to put a TextBox, together with a Label and a SymbolIcon into a Button, so that the whole thing is clickable. at the start you can only see the label and the symbol. By clicking on the button, the label gets hidden and the textBox appears, where you can type some text. By clicking again the label comes up again with the new entered text and the TextBox disappears.
My problem is, that by setting the focus to the TextBox, the button (parent) also seems to get into focus, because everytime you press the spacebar, the Click Event of the button fires. I dont want this to happen, while the TextBox has focus.
XAML
<Button Click="ToggleTopic"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<Grid>
<TextBlock x:Name="textBlockInfoTopic"
Text=""
HorizontalAlignment="Left"
Margin="100,0,100,0"/>
<TextBox x:Name="textBoxTopic"
PlaceholderText="enter Topic..."
HorizontalAlignment="Stretch"
Margin="100,0,100,0"
Visibility="Collapsed"/>
<SymbolIcon x:Name="symbolTopicButton"
Symbol="Add"
HorizontalAlignment="Right"/>
</Grid>
</Button>
C#
private void ToggleTopic(object sender, RoutedEventArgs e)
{
if (textBoxTopic.Visibility == Visibility.Visible)
{
//non edit mode
textBoxTopic.Visibility = Visibility.Collapsed;
textBlockInfoTopic.Visibility = Visibility.Visible;
symbolTopicButton.Symbol = Symbol.Add;
textBlockInfoTopic.Text = textBoxTopic.Text;
}
else
{
//edit mode
textBoxTopic.Visibility = Visibility.Visible;
textBoxTopic.Focus(FocusState.Programmatic);
textBlockInfoTopic.Visibility = Visibility.Collapsed;
symbolTopicButton.Symbol = Symbol.Go;
textBlockInfoTopic.Text = "";
}
}
I only want to prevent the triggering of the event through the spaceBar. The return key should trigger the event.
Thanks for helping me!
D.
From official document,
If a button has keyboard focus, pressing the Enter key or the Space key also raises the Click event. You generally can't handle low-level PointerPressed events on a Button because it has the Click behavior instead.
If you want to prevent SpaceBar from triggering the Click event, you could override OnProcessKeyboardAccelerators method of Button like the following.
public class MyButton : Button
{
protected override void OnProcessKeyboardAccelerators(ProcessKeyboardAcceleratorEventArgs args)
{
if(args.Key == VirtualKey.Space)
{
args.Handled = true;
}
base.OnProcessKeyboardAccelerators(args);
}
}
Usage
<local:MyButton Click="ToggleTopic"
HorizontalAlignment="Stretch"
HorizontalContentAlignment="Stretch">
<Grid IsTapEnabled="False" >
<TextBlock x:Name="textBlockInfoTopic"
Text=""
HorizontalAlignment="Left"
Margin="100,0,100,0"/>
<TextBox x:Name="textBoxTopic"
PlaceholderText="enter Topic..."
HorizontalAlignment="Stretch"
Margin="100,0,100,0"
Visibility="Collapsed"/>
<SymbolIcon x:Name="symbolTopicButton"
Symbol="Add"
HorizontalAlignment="Right"/>
</Grid>
</local:MyButton>

How to keep WPF busy indicator responsive/animated when modal dialog is being parsed and laid out?

I implemented a sample application:
You can select the type that is used for the data grid that is then displayed in the dialog. If the user clicks the button, this code will be executed:
private void ShowDialog()
{
Window dialogView = (Window)Activator.CreateInstance(dialogs[selectedDialog]);
dialogView.ShowDialog();
}
Findings:
If “WPF” is selected, the dialog and DataGrid will be displayed immediately.
If “Infragistics” is selected, it takes more than a second for displaying the dialog and XamDataGrid.
If the “Infragistics” dialog is opened a second time, it will show up much faster.
Then I started profiling and clicked the button for “WPF” and two times “Infragistics”. Here is the timeline for these three clicks:
The XAML of the “Infragistics” dialog looks like this:
<Grid DataContext="{Binding DataGridDialog, Source={StaticResource Locator}}">
<igDP:XamDataGrid DataSource="{Binding Rows}" Width="300" Height="300"/>
</Grid>
The XAML of the “WPF” dialog looks like this:
<Grid DataContext="{Binding DataGridDialog, Source={StaticResource Locator}}">
<DataGrid ItemsSource="{Binding Rows}" Width="300" Height="300"/>
</Grid>
Anyway, the gap between the button click and the “Infragistics” dialog being displayed the very first time is not acceptable for a user. That is why I wrote the following code in the code behind for the "Infragistics" dialog that enables a busy indicator between the events “Initialized” and “Loaded”. Unfortunately the busy indicator's animation is not responsive:
public partial class InfragisticsDataGridDialogView : Window
{
private IUserInteractionService userInteractionService;
private TaskCompletionSource<object> tcs;
public InfragisticsDataGridDialogView(IUserInteractionService userInteractionService)
{
this.userInteractionService = userInteractionService;
Loaded += OnLoaded;
Initialized += OnInitialized;
InitializeComponent();
}
private async void OnInitialized(object sender, EventArgs e)
{
tcs = new TaskCompletionSource<object>();
await ShowBusyIndicatorAsync(tcs.Task);
}
private async Task ShowBusyIndicatorAsync(Task task)
{
await userInteractionService.ShowBusyIndication("Opening dialog", task);
}
private void OnLoaded(object sender, RoutedEventArgs e)
{
tcs.SetResult(null);
}
}
Is there a way to make the busy indicator responsive? The busy indicator is a Grid in the main Window:
<Grid Visibility="{Binding UserInteractionService.ShowBusyIndicator, Converter={StaticResource BoolToVisibilityConverter}}">
<ProgressBar APProgressBar.SubTitle="{Binding UserInteractionService.BusyMessage}" IsIndeterminate="True" />
</Grid>

How to select an item from a listbox in windows phone?

I've a list of data,
Each row will show a data and will have a button, when i click the data shown i want give some data to the previous page and when i click the button in the same row i want to send that same data to next page.
My Xaml code,
<ListBox x:Name="List" HorizontalAlignment="Left" Height="612" Margin="6,7,0,0" VerticalAlignment="Top" Width="443" SelectionChanged="List_SelectionChanged_1">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" Width="420" Height="50">
<TextBlock x:Name="tbName" Width="400" Height="44" FontSize="22" FontWeight="Bold" Text="{Binding Name}" />
<Button x:Name="DetailButton" Height="44" Width="20" Content=">" FontWeight="Bold" Click="DetailButton_Click_1"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
and the code for List_SelectionChanged_1 event handler is,
private void List_SelectionChanged_1(object sender, SelectionChangedEventArgs e)
{
Display selectedItemData = (sender as ListBox).SelectedValue as Display;
NavigationService.Navigate("/Page1.xaml",selectedItemData);
}
and my DetailButton_Click_1 event handler is,
private void DetailButton_Click_1(object sender, RoutedEventArgs e)
{
Display selectedItemData = (sender as ListBox).SelectedValue as Display;
NavigationService.Navigate("/page3.xaml", selectedItemData);
}
Things work fine for *List_SelectionChanged_1*, but i get an exception while executing
Display selectedItemData = (sender as ListBox).SelectedValue as Display;
of the DetailButton_Click_1 , i get an exception a null exception,
An exception of type 'System.NullReferenceException' occurred in ExpenseApp.DLL but was not handled in user code
What should i do make it work?
The underlying problem is that the sender of the button click event is the button, not the ListBox.
Also note that clicking the button on your data template will not necessarily select that item in the list. Try to grab the clicked item's data context and use that instead of .SelectedItem
private void DetailButton_Click_1(object sender, RoutedEventArgs e)
{
var clickedUIElement = sender as Button;
if (null == clickedUIElement) { Return; }
Display selectedItemData = clickedUIElement.DataContext as Display;
if(null != selectedItemData)
{
NavigationService.Navigate("/page3.xaml", selectedItemData);
}
}
Your code, as it stands, will have a null reference since you can't cast a Button as a ListBox.
try verify if the selectvalue is null before execute the code:
private void DetailButton_Click_1(object sender, RoutedEventArgs e)
{
If ((sender as ListBox).SelectedValue != null){
Display selectedItemData = (sender as ListBox).SelectedValue as Display;
NavigationService.Navigate("/page3.xaml", selectedItemData);
}
}

Delete task is not working under Context Menu?

I was developing Windows Phone App using this sample: Local Database Sample
In that sample, Delete Task has been implemented using an icon. I have modified Delete Task by Context Menu. But, it does not works for me.
If I pressed Delete, nothing happens.
I dunno what mistake I have done.
My modified Code:
XAML Code:
<TextBlock
Text="{Binding ItemName}"
FontWeight="Thin" FontSize="28"
Grid.Column="0" Grid.Row="0"
VerticalAlignment="Top">
<toolkit:ContextMenuService.ContextMenu>
<toolkit:ContextMenu Name="ContextMenu">
<toolkit:MenuItem Name="Delete" Header="Delete" Click="deleteTaskButton_Click"/>
</toolkit:ContextMenu>
</toolkit:ContextMenuService.ContextMenu>
</TextBlock>
C# Code:
private void deleteTaskButton_Click(object sender, RoutedEventArgs e)
{
// Cast the parameter as a button.
var button = sender as TextBlock;
if (button != null)
{
// Get a handle for the to-do item bound to the button.
ToDoItem toDoForDelete = button.DataContext as ToDoItem;
App.ViewModel.DeleteToDoItem(toDoForDelete);
MessageBox.Show("Deleted Successfully");
}
// Put the focus back to the main page.
this.Focus();
}
Working original Code in that sample:
XAML Code:
<TextBlock
Text="{Binding ItemName}"
FontSize="{StaticResource PhoneFontSizeLarge}"
Grid.Column="1" Grid.ColumnSpan="2"
VerticalAlignment="Top" Margin="-36, 12, 0, 0"/>
<Button
Grid.Column="3"
x:Name="deleteTaskButton"
BorderThickness="0"
Margin="0, -18, 0, 0"
Click="deleteTaskButton_Click">
<Image
Source="/Images/appbar.delete.rest.png"
Height="75"
Width="75"/>
</Button>
C# Code:
private void deleteTaskButton_Click(object sender, RoutedEventArgs e)
{
// Cast the parameter as a button.
var button = sender as Button;
if (button != null)
{
// Get a handle for the to-do item bound to the button.
ToDoItem toDoForDelete = button.DataContext as ToDoItem;
App.ViewModel.DeleteToDoItem(toDoForDelete);
MessageBox.Show("Deleted Successfully");
}
// Put the focus back to the main page.
this.Focus();
}
In your case sender is not a TextBlock, so this line:
var button = sender as TextBlock;
returns null
You can cast it to MenuItem.
using Microsoft.Phone.Controls;
....
private void deleteTaskButton_Click(object sender, RoutedEventArgs e)
{
var item = sender as MenuItem;
if (item!= null)
{
// Get a handle for the to-do item bound to the button.
ToDoItem toDoForDelete = item .DataContext as ToDoItem;
App.ViewModel.DeleteToDoItem(toDoForDelete);
MessageBox.Show("Deleted Successfully");
}
// Put the focus back to the main page.
this.Focus();
}

Categories

Resources