How to make a simple imgui popup window in C# - c#

Im trying to make a simple popup window where i can input text but i am having a hard time getting started.
internal sealed class UpdatelogWindow : Window, IDisposable
{
public UpdatelogWindow()
: base("What's new?", ImGuiWindowFlags.AlwaysAutoResize | ImGuiWindowFlags.NoResize)
{
this.Namespace = "Update Window";
this.Size = new Vector2(885, 463);
this.SizeCondition = ImGuiCond.Appearing;
}
public override void Draw()
{
ImGui.Text($"Test.");
}
/// <summary>
/// Dispose this window.
/// </summary>
public void Dispose()
{
this.Dispose();
}
}
This is what i have at the moment but nothing is showing up

Related

How do I pass text from form1 to form2 when "both forms are open"

I have two forms "which are both open". I want to send a datagridview cell value from form 1 (already open) to form 2 (already open). (I don't want to pass text on form load, but after some edits on the already open form). I've searched the web for days but I can't find one for already open forms. (Only those containing form.Show() property).
You can create a shared singleton class to keep your data
/// <summary>
/// A singleton class to keep your application data
/// </summary>
public class MySharedData
{
/// <summary>
/// Called when data changes
/// </summary>
public event EventHandler DataChanged;
private static MySharedData _instance;
private object _data;
public static MySharedData Instance => _instance ?? (_instance = new MySharedData());
private MySharedData()
{
}
/// <summary>
/// Gets or sets the data you want to share
/// </summary>
public object Data
{
get => _data;
set
{
_data = value;
OnDataChanged();
}
}
protected virtual void OnDataChanged()
{
DataChanged?.Invoke(this, EventArgs.Empty);
}
}
Use an event to notify che data has updated.
Then in the forms subscribe to the event and add your update logic
public class YourForm : Form
{
public YourForm()
{
MySharedData.Instance.DataChanged += Instance_DataChanged;
}
private void Instance_DataChanged(object sender, EventArgs e)
{
// TODO: redraw your form
}
}

Pass value from main window to child window and then return multiple values from child window to main window

I have a main window and would like to pass a value to a Pop Up window (which will use that value to set up some other values dependant on that value). The pop up window has multiple textboxes for user inputs. When a button called SaveButton is pressed I would like the user inputs (all of them) to be sent back to the main window. How can I accomplish this?
I am very new to C# and I am aware that there are similar questions. However, I am having difficulties with adapting the answers to my specific situation. Thank you for keeping that in mind when answering!
Thank you so much!
Edit: About the code
The code that I have:
For initiating the PopUp window (which is a Window WPF called PopUp)
PopUp popUp = new PopUp();
popUp.ShowDialog
The PopUp.xaml.cs is empty except for the standard stuff and an eventhandler for the click event of the button.
Look at this :
Your main window :
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
//Defining public or internal parameters
public int MainWindowProp1 { get; set; }
public string MainWindowProp2 { get; set; }
public MainWindow()
{
InitializeComponent();
this.Loaded += MainWindow_Loaded;
}
private void MainWindow_Loaded(object sender, RoutedEventArgs e)
{
//When you call your child window, pass this (mainwindow) as parameter.
childWindow cw = new WpfApplication1.childWindow(this);
cw.Param2 = "test";
cw.Param1 = 12;
cw.Closed += Cw_Closed;
cw.ShowDialog();
}
private void Cw_Closed(object sender, EventArgs e)
{
//On closed event, you can cast the sender as your child window.
var child = (sender as childWindow);
var param1 = child.Param1;
var param3 = child.Param2;
}
public void TestMethod()
{
//do anything you want
}
}
}
And your Child Window :
namespace WpfApplication1
{
/// <summary>
/// Interaction logic for childWindow.xaml
/// </summary>
public partial class childWindow : Window
{
//declare Mainwindow as a parameter in your child window
public MainWindow mainWindow;
public int Param1 { get; set; }
public string Param2 { get; set; }
//Add a parameter in your child window contructor.
public childWindow(MainWindow _mainWindow)
{
InitializeComponent();
//Assign your global parameter mainWindow to the _mainWindow parameter.
this.mainWindow = _mainWindow;
this.Loaded += ChildWindow_Loaded;
}
private void ChildWindow_Loaded(object sender, RoutedEventArgs e)
{
//You can get or set your main window properties.
this.mainWindow.MainWindowProp1 = 5;
this.mainWindow.MainWindowProp2 = "test";
//You can call methods ant events etc.. of your main window too (depending on acces modifiers).
this.mainWindow.TestMethod();
}
}
}
In general terms the most simplified solution is this one:
From MainWindow to Child window (Window1);
((Window1)Application.Current.Windows[1]).testlabel.Content = "In Sync";
From child window to MainWindow;
((MainWindow)Application.Current.MainWindow).label2.Content = "whatever";

AutoFixture.Xunit's [Frozen] not working

I have a simple ViewModel which contains some buttons. The visibility of these buttons can be changed by events raised with the EventAggregator of PaP Prism which is also the only constructor parameter of this VM. The corresponding test works just fine when I don't use AutoFixture.
[Theory]
[InfrastructureAutoData]
public void AllButtonsAreShownWhenVisibilityStatusIsSet(
[Frozen]EventAggregator eventAggregator,
ActionBarViewModel sut)
{
eventAggregator
.GetEvent<ActionButtonActivationEvent>()
.Publish(VisibleActionButtons.All);
sut.CancelButtonVisibility.Should().Be(Visibility.Visible);
sut.BackButtonVisibility.Should().Be(Visibility.Visible);
sut.NextButtonVisibility.Should().Be(Visibility.Visible);
sut.Visiblity.Should().Be(Visibility.Visible);
}
Unfortunately, it does not function like it is given here because the EventAggregator instance injected to the ViewModel by AutoFixture is another instance than the one injected into the test.
public class InfrastructureAutoData : AutoDataAttribute
{
public InfrastructureAutoData()
{
Initialize();
}
private void Initialize()
{
this.Fixture.Customize(new AutoMoqCustomization());
Fixture.Register<IEventAggregator>(() => new EventAggregator());
}
}
public class ActionBarViewModel
{
public ActionBarViewModel(IEventAggregator eventAggregator)
{
eventAggregator.GetEvent<ActionButtonActivationEvent>()
.Subscribe(ActivateButtons);
ActivateButtons(VisibleActionButtons.None);
}
/// <summary>
/// Visibility of a button which cancels the current action.
/// </summary>
public Visibility CancelButtonVisibility { get; private set; }
/// <summary>
/// Visibility of a button which loads the previous screen.
/// </summary>
public Visibility BackButtonVisibility { get; private set; }
/// <summary>
/// Visibility of a button with which the next step can be reached.
/// </summary>
public Visibility NextButtonVisibility { get; private set; }
/// <summary>
/// Visibility of the complete view which will be automatically
/// set by the visibile buttons.
/// </summary>
public Visibility Visiblity { get; private set; }
private void ActivateButtons(VisibleActionButtons buttonVisibility)
{
if (buttonVisibility == VisibleActionButtons.All)
{
NextButtonVisibility =
CancelButtonVisibility =
BackButtonVisibility = Visibility.Visible;
}
else
{
NextButtonVisibility =
buttonVisibility == VisibleActionButtons.Next
? Visibility.Visible
: Visibility.Hidden;
CancelButtonVisibility =
buttonVisibility == VisibleActionButtons.Cancel
? Visibility.Visible
: Visibility.Hidden;
BackButtonVisibility =
buttonVisibility == VisibleActionButtons.Back
? Visibility.Visible
: Visibility.Hidden;
}
Visiblity =
buttonVisibility == VisibleActionButtons.None
? Visibility.Collapsed
: Visibility.Visible;
}
}
It seems to me, that the [Frozen] attribute does not work as expected but I am also not sure if a did every thing right. I was also wondering why Inject, instead of Register, does not work. I would have expected that their is no difference.
Thank you for your help.
Edit: I use version 3.7
You're freezing the concrete class EventAggregator, but injecting the interface IEventAggregator. They are two different types, so the IEventAggregator instance you get isn't the frozen EventAggregator.
[Frozen(As = typeof(IEventAggregator))]EventAggregator eventAggregator
should do the trick.

How to deal with a second window

I've got an experience in designing websites with ASP.Net MVC.
I want now to be able to deal with WPF. So, I'm developping a tiny App to learn a few topics like threading, filestreams, and so on.
But, my problem seems really basic :
I've got on my main window a button that fires an action which calls another window. The new windows'aim is to get 2 strings and 2 doubles, to send them back to the main window.
My problem is, that the main window is not launched that way :
MainWindow m = new mainwindow;
And I'd like to do something like :
m.someVariable = somethingFromMySecondWindow.
So, I've tryed to set the main window static, but I got lots of errors, so I removed the "static".
I can't access variables from my second window, or any public method.
I don't know if it is needed, but here is the c# code i've already written.
mainWindow :
namespace FlightPlanningDraft1
{
/// <summary>
/// Logique d'interaction pour MainWindow.xaml
/// </summary>
public partial class MainWindow : Window
{
private string _ACModel;
private string _ACIdentification;
private double _ACFuelConsumption;
private double _ACTotalFuel;
public MainWindow()
{
InitializeComponent();
}
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
ChargementAvion c = new ChargementAvion();
c.Show();
}
public void Validation_Avion(string aCModel,string aCIdentification, double aCFuelConsumption, double aCTotalFuel)
{
_ACModel = aCModel;
_ACIdentification = aCIdentification;
_ACFuelConsumption = aCFuelConsumption;
_ACTotalFuel = aCTotalFuel;
}
}
}
My second window
namespace FlightPlanningDraft1
{
/// <summary>
/// Logique d'interaction pour ChargementAvion.xaml
/// </summary>
public partial class ChargementAvion : Window
{
public ChargementAvion()
{
InitializeComponent();
}
private void Button_Click(object sender, RoutedEventArgs e)
{
//I don't know what to do here.
}
}
}
You can add an event to the second windows. Subscribe on it inside MenuItem_Click (MainWindow), and fire that event from Second window (Button_Click).
You can pass any value to you event.
public partial class ChargementAvion :Window
{
public event Action<string> OnDone;
private void Button_Click(object sender, RoutedEventArgs e)
{
if(OnDone != null)
{
OnDone("any string you want to pass");
}
}
}
and in MainWindow:
private void MenuItem_Click(object sender, RoutedEventArgs e)
{
ChargementAvion c = new ChargementAvion();
c.OnDone += ResultsHandler;
c.Show();
}
public void ResultsHandler(string result)
{
//do what you want ;)
}
I'd suggest you to look through this article. Just to be more familiar with events and delegates in C#.

implementing a progress bar to show work being done

I have one form Form1, and it contains two elements button and progress bar.
When I click on button it calls class.SomeFunction(), which then calls a few other functions from different classes to complete some work.
I would like to increase value of progress bar from inside class.SomeFunctin() and all other functions that SomeFunctino call
class #class
{
public static void SomeFunction(var something)
{
progressbar.value++;
class2.Function2(something);
}
}
class class2
{
public static void Function2(var something)
{
progressbar.value++;
}
}
How can this be done?
You really shouldn't have those functions update the progressbar-- it violates the single responsibility principle. You are better off using a backgroundworker or just update the progressbar from within your button_click event after each function call.
If you are doing something that takes so long you have to show a progress bar, then you should be doing it in a background thread and not the form. That will make the UI become unresponsive.
A Code Project BackgroundWorker Thread article has an example of a background thread that shows a progress bar in a WinForms app.
The easiest way for you to do this is simply to call an event that is handled in your form, and in the event handler have that increment the progress bar.
What you will first want to do is create a custom EventArgs.
public class ProgressEventArgs : EventArgs
{
public int Progress {get; set;}
public ProgressEventArgs(int progress)
{
Progress = progress;
}
}
Then in your classes that you want to increment the Progress bar you will want to raise this event.
class Class2
{
public event EventHandler<ProgressEventArgs> ProgressEvent;
public void Function2(var something)
{
OnRaiseProgressEvent(new ProgressEventArgs(1));
}
protected virtual void OnRaiseProgressEvent(ProgressEventArgs e)
{
// C# 6 and above:
// Raise event if event handler is set (i.e. not null)
ProgressEvent?.Invoke(this, e);
// end C# >=6 code
// C# 5 and earlier:
EventHandler<ProgressEventArgs> handler = ProgressEvent;
if(handler != null)
{
//this is what actually raises the event.
handler(this, e);
}
// end C# <=5 code
}
}
Then in your form you will want to subscribe to the event
public class YourForm
{
public YourForm
{
Class2 yourClass2Instance = new Class2();
yourClass2Instance.ProgressEvent += ProgressEventHandler;
}
private void ProgressEventHandler(object sender, ProgressEventArgs e)
{
progressbar.Value += e.Progress;
}
}
In the past I've used a simple menu bar-less form with a label and a Forms.ProgressBar on it using the following code in the form:
public partial class ProgressDialog : Form
{
//public delegate delSetProgress
private readonly int progressBarMax;
/// <summary>
/// Structure used for passing progress bar related parameters as a single variable.
/// </summary>
public struct ProgressBarParams
{
public int value;
public string message;
public ProgressBarParams(string Message, int Value)
{
message = Message;
value = Value;
}
}
/// <summary>
/// Constructs the progress bar dialog and sets the progress bar's maximum value to maxValue.
/// </summary>
/// <param name="maxValue">Value to set to progress bar's Maximum property.</param>
public ProgressDialog(int maxValue)
{
InitializeComponent();
progressBarMax = maxValue;
}
private void ProgressDialog_Load(object sender, EventArgs e)
{
progressBar.Maximum = progressBarMax;
}
/// <summary>
/// Public method to update the progressDialog
/// </summary>
/// <param name="inputParams">Values to update on the progressDialog</param>
public void SetProgress(ProgressBarParams inputParams)
{
lblMessage.Text = inputParams.message;
progressBar.setValue(inputParams.value);
Update();
}
/// <summary>
/// This method should be called when the operation represented by the ProgressDialog is
/// completed. It shows an "operation complete" message for a second and then closes the form.
/// </summary>
public void Finish()
{
lblMessage.Text = "Operation complete.";
progressBar.setValue(progressBar.Maximum);
Update();
System.Threading.Thread.Sleep(1000);
this.Close();
}
}
public static class MyExtensions
{
/// <summary>
/// Implements a hack to get around a stupid rendering problem with the .NET progress bar in some environments.
/// Sets the progress bar value property.
/// </summary>
/// <param name="proBar">Progress bar control to set the value on.</param>
/// <param name="value">Value to be set.</param>
public static void setValue(this ProgressBar proBar, int value)
{
if (value > 0)
{
proBar.Value = value;
proBar.Value = value - 1;
proBar.Value = value;
}
else
{
proBar.Value = value;
proBar.Value = value + 1;
proBar.Value = value;
}
}
}
Note the setValue extension method that uses a workaround to avoid an issue with some versions of Windows.
I then set it (and a splash screen) up with the following, where m_frmProgress is the progress bar form:
// Create splash screen/progress bar thread on the thread pool
ThreadPool.QueueUserWorkItem((x) =>
{
bool localDone = false;
m_frmSplash.Show();
m_frmProgress.Show();
// Set the progress bar form up slightly below the bottom of the splash screen
m_frmProgress.Location = new Point(m_frmProgress.Location.X, m_frmProgress.Location.Y + (m_frmSplash.Height / 2) + (m_frmProgress.Height / 2) + 10);
while (!localDone) // Keep iterating until the main thread tells us we're done
{
lock (splashScreenDoneLock)
{
localDone = splashScreenDone;
}
// I don't like this method of keeping the UI responsive, but as yet I have no better method
Application.DoEvents();
Thread.Sleep(500);
}
m_frmSplash.Close();
m_frmProgress.Close();
while (!m_frmProgress.IsDisposed || !m_frmSplash.IsDisposed) // While either splash form is not disposed (still active)
{
Thread.Sleep(100); // Keep waiting until the splash forms are gone
}
splashFormsDisposed.Set(); // Signal the main thread that the splash forms are gone so the main form can be shown
});
bool isSplashHandleCreated = false;
bool isProgressHandleCreated = false;
// Wait until both splash forms are created
while (!(isSplashHandleCreated && isProgressHandleCreated))
{
lock (m_frmSplash)
{
isSplashHandleCreated = m_frmSplash.IsHandleCreated;
}
lock (m_frmProgress)
{
isProgressHandleCreated = m_frmProgress.IsHandleCreated;
}
Thread.Sleep(500);
}
And invoke it like this:
m_frmProgress.Invoke(new Action<ProgressDialog.ProgressBarParams>(m_frmProgress.SetProgress), progressLevel);
It's not the most elegant method, but it gives you a cleanly update-able progress bar on a separate thread that will stay responsive while you're messing with it. I pretty much copy and pasted all that code from a working app, so it should work. On the flip side, I apologize if any of it is unclear.

Categories