I am listening to the PreviewMouseUp event of a ToggleButton control. Depending on a condition the click event should be raised normally or aborted completely. So the IsChecked property is only set if the condition is true. For this I use the MouseButtonEventArgs.Handled property that is set to false if the condition is false.
If the ToggleButton is clicked and the condition is false the IsChecked property is not set as expected. But the application freezes for no reason. No further button clicks are possible.
If you click into the taskbar (context lost) the application is working again.
MainWindow.xaml
<Window x:Class="ButtonEventTest.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"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<ToggleButton Content="Test Button"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Padding="10"
PreviewMouseUp="UIElement_OnPreviewMouseUp"/>
</Grid>
</Window>
MainWindow.xaml.cs
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void UIElement_OnPreviewMouseUp(object sender, MouseButtonEventArgs e)
{
if (!IsMouseClickAllowed())
{
e.Handled = true;
}
}
}
Is there something that I am missing? Or is this a known WPF bug?
Related
I have two windows in a single application.
The first window has one button. When I click the button, the second window opens. (The first window needs to close or hide). Then I need to close my second window and need to stop the debugging. How to do it?
<Window x:Class="WpfApp5.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:WpfApp5"
xmlns:syncfusion="http://schemas.syncfusion.com/wpf"
xmlns:Control="clr-namespace:Syncfusion.Windows.Tools.Controls;assembly=Syncfusion.Tools.Wpf"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button Content="Create" Height="50" Width="100" Click="btncreate"></Button>
</Grid>
MainWindow code-behind:
public partial class MainWindow : Window
{
public static TextBox textBox;
public MainWindow()
{
InitializeComponent();
}
private void btncreate(object sender, RoutedEventArgs e)
{
SecondWindow secondWindow = new SecondWindow();
secondWindow.Owner = this;
this.Hide();
secondWindow.ShowDialog();
}
}
Second window:
<Window x:Class="WpfApp5.SecondWindow"
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:WpfApp5"
mc:Ignorable="d"
Title="SecondWindow" Height="450" Width="800">
<Grid>
<StackPanel>
<TextBlock Text="New Project Loaded" HorizontalAlignment="Center" Margin="50"></TextBlock>
</StackPanel>
</Grid>
Your problem seems to be that you're running code which is showing a window, maybe modally.
At the same time, you're trying to shut the app down.
You've not shown this code but if your btnCreate handler has shutdown in it just before
secondWindow.ShowDialog();
You'd be trying to shut the app down effectively at the same time as showing that window as a dialog.
What you want is your code to shut the app down but not whilst the UI is busy doing something else like show a window.
You could do that by moving your shutdown so it's in say the contentrendered event handler of that window you're showing.
Another option is to schedule the shutdown using dispatcher.
Application.Current.Dispatcher.InvokeAsync(new Action(() =>
{
Application.Current.Shutdown();
}), DispatcherPriority.ContextIdle);
If you still have errors you could consider instead using.
Environment.Exit(0);
This is a rather brute force approach compared to shutdown but if you're only doing this whilst debugging that probably won't matter.
In any case, you should ensure you don't have code which shows another window or something from the window.closing events of any of your windows. Since closing the app will necessarily involve closing windows.
I am trying to bring up a window as a loading screen using the system.windows.window.show() method. The program is supposed continue running code and then close the window after it is done. The problem is that the window will not show the textblock I am trying to display. But when I do ShowDialog() it will
LoadingWindow lw = new LoadingWindow();
lw.Show();
//
//do stuff
//
lw.Close();
<Window x:Class="RevitAPITest3.LoadingWindow"
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:RevitAPITest3"
mc:Ignorable="d"
Title="Loading..." Height="450" Width="800" >
<Grid>
<TextBlock x:Name="text" FontSize="20" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Height="43" Width="291">testing</TextBlock>
</Grid>
</Window>
There's a fundamental difference between lw.Show() and lw.ShowDialog().
lw.Show() will immediately return to the next line of code without waiting for the window to close.
lw.ShowDialog() will wait for the window to close manually by the user, then return a value of true/false.
In your example code, your problem is that because lw.Show() returns immediately, it will then "do stuff" and then call lw.Close() which closes your window before you even see the window.
What you'll want to do is something like this. Notice: You never have to explicitly call lw.Close() because the window will automatically be closed as soon as it completes the lw.ShowDialog() line.
var result = lw.ShowDialog();
if (result.HasValue)
{
//
//do Stuff
//
}
Here is a complete working solution. Check to see where you are doing things differently and see if you can match this implementation.
MainWindow.xaml
<Window x:Class="LoadingWindowTest.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="MainWindow" Height="768" Width="1024" WindowStartupLocation="CenterScreen">
<Grid>
<TextBlock Text="Main Window" HorizontalAlignment="Center" VerticalAlignment="Center" FontSize="32"/>
</Grid>
</Window>
MainWindow.xaml.cs
using System.Threading.Tasks;
using System.Windows;
namespace LoadingWindowTest
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private LoadingWindow lw;
public MainWindow()
{
InitializeComponent();
this.Loaded += OnLoaded;
}
private async void OnLoaded(object sender, RoutedEventArgs e)
{
// Make the main window hidden until loading is done
this.Visibility = Visibility.Hidden;
// Show the Loading window
lw = new LoadingWindow();
lw.Show();
// Simulate a long running task
await Task.Delay(5000);
// Close the Loading window
lw.Close();
// Show the Main Window
this.Visibility = Visibility.Visible;
}
}
}
LoadingWindow.xaml (no xaml.cs shared because I didn't touch it)
<Window x:Class="LoadingWindowTest.LoadingWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
mc:Ignorable="d"
Title="LoadingWindow" Height="450" Width="800" WindowStartupLocation="CenterScreen">
<Grid>
<Grid>
<TextBlock x:Name="text" FontSize="20" HorizontalAlignment="Left" TextWrapping="Wrap" VerticalAlignment="Top" Height="43" Width="291">testing</TextBlock>
</Grid>
</Grid>
</Window>
Build and Run, then this is the Expected Output:
You should see the LoadingWindow on the center of the screen, then after 5 seconds, it closes and the MainWindow shows.
I have a context menu what is triggered by each list item of listbox.
And, I want to create child window when I select a context menu as below:
xaml
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Width="150" Orientation="Vertical" Margin="15, 5, 15, 5">
<StackPanel.ContextMenu>
<ContextMenu FontSize="16">
<MenuItem Header="{x:Static localRes:Resources.ID_STRING_SETTING}" Margin="5" Command="Setting_Click"/>
</ContextMenu>
It is already a sub page of main window.
So, I can't find a way how to set MainWindow instance as the owner of new window.
Behind Code
private void Setting_Click(object sender, RoutedEventArgs e)
{
SettingWindow SettingWindow = new SettingWindow();
SettingWindow.Owner = /* I do not know how to do */
SettingWindow.Show();
}
If your click command handler is in the code behind for your main window, then you need to set
deviceSettingWindow.Owner = this;
https://learn.microsoft.com/en-us/dotnet/api/system.windows.window.owner?view=netframework-4.8
Here's a small example. It includes a button with a handler whose code is in the code behind -
<Window x:Class="MainWindow.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:ChildWindow"
mc:Ignorable="d"
Title="MainWindow" Height="450" Width="800">
<Grid>
<Button Content="Button" HorizontalAlignment="Left" Margin="114,137,0,0" VerticalAlignment="Top" Width="75" Click="Button_Click"/>
</Grid>
</Window>
CodeBehind:
using System.Windows;
namespace MainWindow
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
var childWindow = new ChildWindow.Window1();
childWindow.Owner = this;
childWindow.Show();
}
}
}
Child Window - just an empty window
<Window x:Class="ChildWindow.Window1"
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:ChildWindow"
mc:Ignorable="d"
Title="Window1" Height="450" Width="800">
<Grid>
</Grid>
</Window>
Child Window Code Behind
using System.Windows;
namespace ChildWindow
{
/// <summary>
/// Interaction logic for Window1.xaml
/// </summary>
public partial class Window1 : Window
{
public Window1()
{
InitializeComponent();
}
}
}
In my example, Since you are in the code behind for the MainWindow, this is a reference to the MainWindow, and setting 'childWindow.Owner = this' is setting the childWindow's owner to the MainWindow which is what I believe you want.
One thing that is a little confusing to me is that you are using a Command and a reference to an event handler in the code behind. I'm pretty sure that's not going to work. Commands need to Bind to an ICommand reference - you'll have to implement your own ICommand class, or use one from MVVM Light or another WPF MVVM Framework. Once you've got that you can pass a reference from the parent window through the Command as a CommandParameter. For an example of how to do this, see passing the current Window as a CommandParameter
If you are using an event handler on a control, then that can bind to the event handler implementation in the code behind like in my example. You need to choose one or the other.
If you're able to provide more details on how you're setup, it would make it easier for me to provide input on which way you need to go.
I have a UserControl which is shown in a popup. I have a button in usercontrol that on clicking, makes a textfield visible. But as again i visit that usercontrol, the textfiled remains visible, i want it to be again collapsed until user clicks the button.
I have no clue how to do that? which method to override. please help me
use the UserControl.Loaded event to set your textfield to collapsed.
This blogpost about the Loaded and Initialized Event was very helpful for me.
Example:
UserControl XAML
<UserControl x:Class="YourNamespaceName.YourClassName"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" Loaded="YourClassName_OnLoaded">
<Grid>
<TextBlock x:Name="testTextBlock" Text="Invisible on startup" />
<Button x:Name="testButton" Content="Click" Click="TestButton_OnClick" />
</Grid>
</UserControl>
UserControl CodeBehind
private void YourClassName_OnLoaded(object sender, System.Windows.RoutedEventArgs e)
{
this.testTextBlock.Visibility = Visibility.Collapsed;
}
private void TestButton_OnClick(object sender, RoutedEventArgs e)
{
this.testTextBlock.Visibility = Visibility.Visible;
}
I have a window with a Grid on.
On this I have some buttons, one of which when clicked will create a new 'PostIt' which is a user control I have created.
What I want to do is click on a 'PostIt' and have that control on top of all the others.
I have tried...
Grid.SetZIndex(sender, value);
Which seems to be the correct code, no errors, just not movement of the control :(
The problem may lie in the fact that the code for the click is in the user control and not the mainwindow cs file. Does this matter?
The 'PostIt' is simply a border with a text box in it.
Are you calling Grid.SetZIndex(sender, value) in a handler of the PostIt mouse click, or a handler for a control inside the PostIt? What is the value that you are setting?
Here is an example that works:
<UserControl x:Class="WpfApplication1.UserControl1"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
mc:Ignorable="d"
d:DesignHeight="300" d:DesignWidth="300" MouseUp="UserControl_MouseUp">
<Grid>
</Grid>
</UserControl>
public partial class UserControl1 : UserControl
{
public UserControl1()
{
InitializeComponent();
}
private void UserControl_MouseUp(object sender, MouseButtonEventArgs e)
{
Panel.SetZIndex(this, Panel.GetZIndex(this) + 2);
}
}
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:WpfApplication1"
Title="MainWindow" Height="350" Width="525">
<Grid>
<local:UserControl1 Background="Green" Margin="40,40,100,100" Panel.ZIndex="0" />
<local:UserControl1 Background="Red" Margin="140,140,10,10" Panel.ZIndex="1" />
</Grid>
</Window>
Jogy
This may not be the best solution, but it's the one that worked for me; I was re-ordering two grids:
GridOnBottom.SetValue(Grid.ZIndexProperty, (int)GridOnTop.GetValue(Grid.ZIndexProperty) + 1);
...with GridOnBottom and GridOnTop renamed to the instances of the objects you're re-ordering. Granted, it's not the best solution, but it works.