How to show and hide the Popup? - wpf

void Start()
{
System.Windows.Controls.Primitives.Popup p = new System.Windows.Controls.Primitives.Popup();
p.HorizontalOffset = this.ActualWidth / 2;
p.Width = 100;
p.Height = 100;
p.VerticalOffset = this.ActualHeight / 2;
DockPanel dock = new DockPanel();
dock.Children.Add(new Button() { Content = "Обновлено" });
p.Child = dock;
p.IsOpen = true;
Thread t = new Thread(StopPopup);
t.Start(p);}
function:
private void StopPopup(object obj)
{
try
{
System.Windows.Controls.Primitives.Popup p = (System.Windows.Controls.Primitives.Popup)obj;
this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() =>
{
dataGrid1.DataContext = DataSetCreator.AllItems();
Thread.Sleep(1500);
p.IsOpen = false;
}));
}
catch (Exception ex) { MessageBox.Show(ex.Message); }
but why this code is triggered once = (
}

It looks like you're trying to show a control from a non-UI thread and not connecting it to the Application UI in any way (as far as I can see here). WPF UI elements need to created and manipulated on the UI thread and need to be associated with some Window based control in order to be rendered.

In addition to what John said, I would suggest looking at a Modeless dialog box. When you call Show() on the dialog box, the method returns immediately. This allows the application to continue instead waiting for a response from the dialog. You can also attach to button's click event so you know when the button is clicked.

Related

How to move window using custom titlebar in MAUI Blazor

I have a problem with move application.
Window movement works fin, but releasing the button does not work, it moves the window all the time after releasing the left mouse button.
Titlebar razor
<div #onpointerdown="() => topbarVM.MouseDown()" #onpointerup="() => topbarVM.MouseUp()" class="flex-row fixed-top p-0 m-0">
Code
public void MouseDown()
{
isDown = true;
DragWindow();
}
public void MouseUp()
{
isDown = false;
}
public void DragWindow()
{
#if WINDOWS
var mauiWindow = App.Current.Windows.First();
var nativeWindow = mauiWindow.Handler.PlatformView;
IntPtr windowHandle = WinRT.Interop.WindowNative.GetWindowHandle(nativeWindow);
WindowId WindowId = Win32Interop.GetWindowIdFromWindow(windowHandle);
AppWindow appWindow = AppWindow.GetFromWindowId(WindowId);
while(isDown)
{
var cursor = GetCursorPosition();
appWindow.Move(new Windows.Graphics.PointInt32(cursor.X - 40, cursor.Y - 20));
};
#endif
}
Put a breakpoint inside MouseUp. Is it ever reached? If not, then your code is keeping MainThread (UI thread) busy, so MouseUp event cannot get processed.
One way to code this (in any UI framework) is to do ONE call on the MouseMove event -- not a loop:
public void MouseMove() {
if (isDown)
{
var mauiWindow ...
...
var cursor = GetCursorPosition();
appWindow.Move(...
}
}
Reference MouseMove() from an appropriate event in your Blazor code. I don't know Blazor, so I don't show that.
Explanation: after the Move is done, MouseMove returns. This allows internal OS code to process the next event.

wpf threading, thread must be STA

I have a window(say main window) with a frame which has a page in it. A button on the page opens another window(say popup window). Now i am trying to invoke a method in the main window from a button on the popup window. The method has to be multi-threaded, i had a similar solution running in windows forms but i keep getting the calling thread must be STA because many UI components require this in WPF.
The method on the page which opens the popup window modally
Scripts showStocks = new Scripts();
showStocks.ShowInTaskbar = false;
showStocks.ShowDialog();
if (showStocks.DialogResult==true)
{
Window1 wd1 = new Window1();
wd1.doneDeal();
}
Here window1 is our main window. The doneDeal method is
public void doneDeal()
{
// **Some Code**
BackgroundWorker wworks1 = new BackgroundWorker();
wworks1.DoWork += Tickes;
wworks1.RunWorkerCompleted += Tickes2;
wworks1.RunWorkerAsync();
// Page1 pg1 = frame1.Content as Page1;
//NextPrimeDelegate dd=new NextPrimeDelegate(okreport);
// pg1.addScriptBtn.Dispatcher.BeginInvoke(DispatcherPriority.Normal,
// new NextPrimeDelegate(okreport));
//startStopButton.Dispatcher.BeginInvoke(
// DispatcherPriority.Normal,
// new NextPrimeDelegate(CheckNextNumber));
//new Thread(() => Tick(stock, rowID, exchange)) { IsBackground = false }.Start();
}
Finally the method that i am trying to run in the background
public void Tickes(object sender, DoWorkEventArgs e)
{
}
Also i want to populate a gridview from the result of the tickes method, this will be looping and running over and over in the background but periodically returning data to be added to the grid. SHould i do that in the progress update event ? Have tried a lot to wrap my head around the dispatcher and background worker in wpf but am failing to understand the STA apartment state bit. If someone can help me to get my tickes method going or point me in the right direction, i would be very very thankful.
Well i finally was able to solve the STA thread problem am posting the answer just in case somebody comes across a similar problem in the future.
public void doneDeal()
{
if (StockData.flag == 1)
{
row1 = table.NewRow();
row1[col1] = "";
row1[col2] = "";
row1[col3] = "";
row1[col4] = "";
row1[col5] = "";
row1[col6] = "";
row1[col7] = "";
row1[col8] = "";
row1[col9] = "";
row1[col10] = "";
row1[col11] = "";
row1[col12] = "";
table.Rows.Add(row1);
string stock = StockData.stock;
int rowID = (table.Rows.Count - 1);
string exchange = StockData.exchange;
Thread bh = new Thread(delegate()
{
Tick7(stock, rowID, exchange);
});
bh.SetApartmentState(ApartmentState.STA);
bh.IsBackground = true;
bh.Start();
StockData.flag = -1;
}
}
The Tick7 method which is being called is declared like this
[STAThread]
public void Tick7(string stock, int rowID, string exchange)
{
int rowNum = rowID;
int counter = -1;
deletecounter = StockData.deletecounter;
Thread.CurrentThread.Name = StockData.stock;
.
.
.
}

How to stop a new window to be opened every time?

I have a WPF application in which on a click of a menu item a window is opened. If the same menu item is clicked again when the window is already open, it is opening a new window but I don't want a new window to be opened every time.
What I need is, if the window is already open, the same window should be focused not a new window.
//First we must create a object of type the new window we want the open.
NewWindowClass newWindow;
private void OpenNewWindow() {
//Check if the window wasn't created yet
if (newWindow == null)
{
//Instantiate the object and call the Open() method
newWindow= new NewWindowClass();
newWindow.Show();
//Add a event handler to set null our window object when it will be closed
newWindow.Closed += new EventHandler(newWindow_Closed);
}
//If the window was created and your window isn't active
//we call the method Activate to call the specific window to front
else if (newWindow != null && !newWindow.IsActive)
{
newWindow.Activate();
}
}
void newWindow_Closed(object sender, EventArgs e)
{
newWindow = null;
}
I think this solve your problem.
Att,
If your opened windows is used as simple dialog box you can use following code
window.ShowDialog();
when the dialog will show you cannot press any menu items unit you close this window
A rather brute force approach like this also works:
bool winTest = false;
foreach (Window w in Application.Current.Windows)
{
if (w is testWindow)
{
winTest = true;
w.Activate();
}
}
if (!winTest)
{
testWindow tw = new testWindow();
tw.Show();
}
You can create a field and check if it's set:
private Window _dialogue = null;
private void MaekWindowButton_Click(object sender, RoutedEventArgs e)
{
if (_dialogue == null)
{
Dialogue diag = new Dialogue();
_dialogue = diag;
diag.Closed += (s,_) => _dialogue = null; //Resets the field on close.
diag.Show();
}
else
{
_dialogue.Activate(); //Focuses window if it exists.
}
}

Silverlight & C# - Open a childwindow only if a time frame passes

Hopefully the title makes sense but I will discribe my issue. I am using a childwindow in Silverlight to display a Processing message and rotating image when the UI is doing some work. Once a Completed Event is called, the window then closes.
Problem is that it does look a little ugly when the UI performs a quick task as the child window opens and then closes in under 1 second.
What I want to be able to do is have the child window open only if 2 seconds of processing has passed and then close on complete.
I have added a section of my xaml where I am calling the child below. I have searched but cannot find anything on this and it might not be possible.
void edit_Closed(object sender, EventArgs e)
{
EditChannelDetails edit = sender as EditChannelDetails;
if (edit.DialogResult == true)
{
if (edit != null)
{
Channel edited = new Channel();
edited.channelId = Int32.Parse(edit.ChannelID.Text);
edited.name = edit.ChannelName.Text;
edited.description = edit.ChannelDescription.Text;
ChannelClient proxy = new ChannelClient(new BasicHttpBinding(), new EndpointAddress("http://servername"));
proxy.UpdateChannelCompleted += new EventHandler<UpdateChannelCompletedEventArgs>(proxy_UpdateChannelCompleted);
proxy.UpdateChannelAsync(edited);
}
}
processingDialog.Show();
}
void proxy_UpdateChannelCompleted(object sender, UpdateChannelCompletedEventArgs e)
{
processingDialog.Close();
Etc.....
Boolean closeFlag = false;
Start a timer:
DispatcherTimer timer = new DispatcherTimer() { Interval = TimeSpan.FromSeconds(2) };
timer.Tick += (tts, tte) => {
timer.Stop();
closeFlag = true;
};
timer.Start();
And check flag:
if (!closeFlag)
{
processingDialog.Close();
}

How do I access a MessageBox with white?

I have a simple message box in a WPF application that is launched as below:
private void Button_Click(object sender, RoutedEventArgs e)
{
MessageBox.Show("Howdy", "Howdy");
}
I can get white to click my button and launch the message box.
UISpy shows it as a child of my window I couldn't work out the method to access it.
How do I get access to my MessageBox to verify its contents?
Found it! The window class has a MessageBox method that does the trick:
var app = Application.Launch(#"c:\ApplicationPath.exe");
var window = app.GetWindow("Window1");
var helloButton = window.Get<Button>("Hello");
Assert.IsNotNull(helloButton);
helloButton.Click();
var messageBox = window.MessageBox("Howdy");
Assert.IsNotNull(messageBox);
Please try this
Window messageBox = window.MessageBox("");
var label = messageBox.Get<Label>(SearchCriteria.Indexed(0));
Assert.AreEqual("Hello",label.Text);
Contained in the White source code are some UI tests projects (to test White itself).
One of the test includes MessageBox tests, which includes a way to obtain the displayed message.
[TestFixture, WinFormCategory, WPFCategory]
public class MessageBoxTest : ControlsActionTest
{
[Test]
public void CloseMessageBoxTest()
{
window.Get<Button>("buttonLaunchesMessageBox").Click();
Window messageBox = window.MessageBox("Close Me");
var label = window.Get<Label>("65535");
Assert.AreEqual("Close Me", label.Text);
messageBox.Close();
}
[Test]
public void ClickButtonOnMessageBox()
{
window.Get<Button>("buttonLaunchesMessageBox").Click();
Window messageBox = window.MessageBox("Close Me");
messageBox.Get<Button>(SearchCriteria.ByText("OK")).Click();
}
}
Evidently, the label used to display the text message is owned by the window displaying the messagebox, and its primary identification is the max word value (65535).
window.MessageBox() is a good solution!!
But this method would stuck for a long time if the messagebox doesn't appear. Sometimes I want to check "Not Appearance" of a messagebox (Warning, Error, etc.). So I write a method to set the timeOut by threading.
[TestMethod]
public void TestMethod()
{
// arrange
var app = Application.Launch(#"c:\ApplicationPath.exe");
var targetWindow = app.GetWindow("Window1");
Button button = targetWindow.Get<Button>("Button");
// act
button.Click();
var actual = GetMessageBox(targetWindow, "Application Error", 1000L);
// assert
Assert.IsNotNull(actual); // I want to see the messagebox appears.
// Assert.IsNull(actual); // I don't want to see the messagebox apears.
}
private void GetMessageBox(Window targetWindow, string title, long timeOutInMillisecond)
{
Window window = null ;
Thread t = new Thread(delegate()
{
window = targetWindow.MessageBox(title);
});
t.Start();
long l = CurrentTimeMillis();
while (CurrentTimeMillis() - l <= timeOutInMillsecond) { }
if (window == null)
t.Abort();
return window;
}
public static class DateTimeUtil
{
private static DateTime Jan1st1970 = new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc);
public static long currentTimeMillis()
{
return (long)((DateTime.UtcNow - Jan1st1970).TotalMilliseconds);
}
}

Resources