value wont change in an event - c#

I've create a list of canvases in wpf, and I have a button click event. I want that when I press the button it will add to the list new canvas. but when I try to change the property of the canvas in another window, it says the index was out of bounds, which means the list didnt add the canvas. I've created a method to check that and indeed it says the index is 0.
I've this with an array also, same here, I change its value but its still wrote the value is 0. this is the code:
public partial class New_Paint : Window
{
public List<Canvas> paintsList = new List<Canvas>();
public Canvas painting = new Canvas();
private void ok_MouseUp(object sender, MouseButtonEventArgs e)
{
paintsList.Add(painting);
this.Close();
}
}
and this is the moethod to check its size:
public int getSize()
{
return paintsList.Count;
}
and here is the code in the main window:
private void button1_Click(object sender, RoutedEventArgs e)
{
textBox1.Text = paint.getSize() + "";
}
the methos return 0 although i click "ok". the list just wont add the items.

I take it you're new at this? Your list of canvases belong to your instance of New_Paint, and you only add one canvas to that list before closing the window (at least in the code you've shown). I don't see why you would expect more than one. You need to have a master list of canvases that is owned by whatever is managing your child windows.

Related

How to access form's location propertie?

So I have class 'employee' in which I have the properties double X and double Y and I want to bind these two to the form's location. (top left corner) I have tried to do it using How to get the position of a Windows Form on the screen?
but it only gives the value which is not helpful.
How can I access the actual properties?
So far have tried:
this.Left.DataBindings.Add("Value", EmpNd, "ThisEmployee.X", true, DataSourceUpdateMode.OnValidation);
Say you have two text boxes that will display X and Y coordinates of the form. In your form's Load event, you can bind the form's DesktopLocation.X and DesktopLocation.Y properties like so:
private void Form1_Load(object sender, EventArgs e)
{
txtX.DataBindings.Add("Text", this.DesktopLocation.X, null);
txtY.DataBindings.Add("Text", this.DesktopLocation.Y, null);
}
If you want the text boxes to display the updated value as you move your form, you can declare a method that does this, and call it whenever Form_Move() event occurs:
private void Form1_Move(object sender, EventArgs e)
{
RefreshDataBindings();
}
public void RefreshDataBindings()
{
txtX.DataBindings.Clear();
txtY.DataBindings.Clear();
txtX.DataBindings.Add("Text", this.DesktopLocation.X, null);
txtY.DataBindings.Add("Text", this.DesktopLocation.Y, null);
}

Visual Studio C #, Loop

Visual Studio C #
I made a calculator, and now I have to make a calculator memory (event).
There are 4 components other than the calculator: one Textbox for the answer of the calculator, two Buttons for "M" and "M+", and one Lable to display the answer again.
When the user clicks the “M” button, the contents of the Answer TextBox should be copied to a memory variable. Also make it so that when the user moves the mouse over the label, the value in the memory variable will appear in this label, and then disappear, when the mouse moves away from the label. Also add one more button, an “M+” button. When the user clicks this button, the contents of the Results box will be added to Memory. You will need to use a Global Variable to store this data.
My problem is that the label doesn't appear when the mouse over the label, and also it doens't disappear when the mouse leave the label. How can I fix it?
And also, is this way the right way to use the Global variable?
Below is my code (I just put the code for "M" and "M+" buttons, not the code for the calculator).
private String ans;
private Double answer;
private Double answerPlus;
private void btnM_Click(object sender, EventArgs e)
{
ans = txtDisplay.Text;
answer = double.Parse(ans);
lblblank.Text = answer.ToString();
}
private void lblblank_MouseEnter(object sender, EventArgs e)
{
lblblank.Show();
lblblank.Text = answer.ToString();
}
private void lblblank_MouseLeave(object sender, EventArgs e)
{
lblblank.Hide();
}
private void btnMplus_Click(object sender, EventArgs e)
{
answerPlus = answer + double.Parse(ans);
lblblank.Text = answerPlus.ToString();
}
Storing variables
The way you store your values is fine.
Events
Once you call .Hide() the next MouseEnter/MouseLeave-event will not be triggered anymore. What you could do is to take a panel, or any layout element as a wrapper/parent-element for the label and then adjust your event-callbacks to something like that:
private void panel_MouseEnter(object sender, EventArgs e)
{
lblblank.Show();
lblblank.Text = answer.ToString();
}
private void panel_MouseLeave(object sender, EventArgs e)
{
lblblank.Hide();
}
Edit
~~~
What does it mean that any layout element as a parent-element for the
label? Could you explain more?
What I meant was to just create a new panel (or layout-element) and put the label into it as a child. See the picture below:
If you set that up correctly, the code snippet I posted above will work just fine. This solution does not prevent the MouseLeave event from triggering when your mouse enters the label. Therefore you could use an alternative solution using the MouseMove event.
Alternative
using System;
using System.Windows.Forms;
using System.Drawing;
namespace WindowsFormsApp1
{
public partial class Form1 : Form
{
public Form1()
{
this.InitializeComponent();
// Subscribe to the MouseMove event
this.panel.MouseMove += this.panel_MouseMove;
}
private void panel_MouseMove(object sender, MouseEventArgs e)
{
// Checks if current mouse position is within the panel
if (this.panel.Bounds.Contains(new Point(e.X, e.Y)))
{
// Current mouse position within the panel
this.label.Show();
return;
}
// Current mouse position outside the panel
this.label.Hide();
}
}
}

Find location of a control in wpf using PointToScreen

I'm trying to find my relative coordinate for a usercontrol inside my mainwindow. I tried using the "Control.PointToScreen()" method but with no luck. Everytime I do this i get an exception that says:
System.InvalidOperationException: This Visual is not connected to a PresentationSource
I think this has something to do with me calling pointToScreen before the visuals have rendered properly, since i'm already calling the method in my Mains Constructor.
Anyways, I would like to hear if anyone of you had a hint/Solution/Idea how I could perhaps work around this.
Just to clearify what i'm trying to do, my control contains a photocontrol which i need the exact location off inside my maincontrol, since i want to use these coordinates to create a duplicate of the control on top of it
Experimenting with PointToScreen.
In your code register for the Loaded event of the UserControl.
That should fix the bug that the visuals have not been rendered yet when you try to get the position.
YourControl.Loaded += ControlLoaded;
public void ControlLoaded(object sender, EventArgs e){
Console.WriteLine(YourControl.PointToScreen(new Point(0,0));
}
Edit
Since you want the position of your control relative to your window, better try that one .
YourControl.TransformToAncestor(YourWindow).Transform(new Point(0,0))
Since Contend rendered didn't work I found a solution for my problem.
private void UserControl_Loaded(object sender, RoutedEventArgs e)
{
ItemsControl ItemsControl = UCEnvironmentControl.GetItemsControlPhotos();
Dispatcher.BeginInvoke(DispatcherPriority.Loaded, new Action(() => Control.PointToScreen(new Point(0,0));
}
This way, it fires in the LoadedEvent, but waits for the content to be rendered, and then finally it gives you your coordinate back and sets your control
The solution from Max Mazur is working for me:
public partial class MainWindow : Window
{
Point locationOfYourControl;
public MainWindow()
{
InitializeComponent();
this.ContentRendered += MainWindow_ContentRendered;
}
private void MainWindow_ContentRendered(object sender, EventArgs e)
{
locationOfYourControl = YourControl.PointToScreen(new Point(0, 0));
}
}

selecting enum as SelectedItem in combobox

I struggle with selecting proper item in winforms combobox. Previously I described in detail here but I think that problem remain unsolved cause I use one form for add/edit record. so on form load I have
private void AddEditForm_Load(object sender, EventArgs e)
{
PopulateComboBoxLanguage();
}
private void PopulateComboBoxLanguage()
{
comboBoxLang.DataSource = Enum.GetValues(typeof(Book.EnumLang));
}
and on edit action I want to populate form with existing data and everything is populated as it should except combobox where first item from EnumLang is always displayed.
from my second constructor I call PopulateWithExisingData(book) where I use
comboBoxLang.SelectedItem = book.Language;
but even when passed book.Language is set to German SelectedItem is always null on debug mode.
p.s. I tried with comboBoxLang.SelectedItem = (book.EnumLang)book.Language; also with SelectedValue but remains the same.
Once more I guess that problem is on populating combobox on page load but I don't know is it and how to fix that.
Please ask for more info.
Declare an instance of the object type you are adding/editing in your form.
Add a bool isEdit to the form and set it to false
Add a method public void Initialize(ObjectType name)
Your Initialize method should set the form instance equal to the parameter and it should set a boolean flag isEdit = true.
Put all your code that loads data/populates controls (like your combobox) in your forms load event.
At the bottom of your load event, after your controls are populated do
if (isEdit)
{
//Set your controls selected values from the object you are editing
}
Now, for new objects, just make your form and call a Show or a ShowDialog on it. This will cause the Load event to fire and your controls will populate.
For edits, make your form, call Initialize, THEN do the Show/ShowDialog. Since your Initialize method sets isEdit = true, the if(isEdit) block of code at the bottom of your load event will be hit and the controls values will be set equal to the properties of the object you are editing.
Here is some very simple example code:
public Form1()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
//This is simulating an add...First Language will be displayed on form2,
//which is English
Form2 form = new Form2();
form.ShowDialog();
}
private void button2_Click(object sender, EventArgs e)
{
//This is simulating an edit...this will display french
//(or whatever is passed in)
Form2 form = new Form2();
form.Initialize(Languages.French);
form.ShowDialog();
}
Languages editValue;
bool isEdit = false;
public Form2()
{
InitializeComponent();
}
public void Initialize(Languages var)
{
editValue = var;
isEdit = true;
}
private void Form2_Load(object sender, EventArgs e)
{
comboBox1.DataSource = Enum.GetValues(typeof(Languages));
if (isEdit)
{
comboBox1.SelectedItem = editValue;
}
}
public enum Languages
{
English = 0,
French = 1,
Spanish = 2,
German = 3
}
When you set DataSource, you pass an array of objects.
When you set SelectedItem, you pass an enum value, so it gets boxed to an object again. ComboBox searches for your item among the DataSource values, using method IndexOf, which uses method Object.Equals to compare those values against your new value. And since they are different objects (the references differ), your item is never found in the DataSource collection, so the selection is not changed.

Is it possible to define a class-scope objet from a method?

This may seem totally unreasonable to ask, but I have been designing a multi-panel, real device simulator, that has many different screens and my current approach is to add all the screen objects from the code only and dispose them when I switch to another screen.
I have some fixed objects, that are the real device buttons that are already defined and in place. The thing is, I am separating each panel construction in methods, for example: buildLogin(), buildMainScreen(), etc, and I need to edit some of the screen objects from those methods, like changing the color of an enabled function label to green if enabled or white if disabled.
My question is: would it be possible to declare an object from a method that would be accessible in the whole class, like if it were defined in the variable declaration section? It would be something like the GLOBAL in PHP.
I can't declare it on top of everything like they would always be because when I dispose the objects, I can't "re-create" them, because of parenting, or re-using a disposed object or something...
[EDIT] Sample code:
public partial class frmMain : Form
{
//I could as well do this:
//Button button1 = new Button();
public frmMain()
{
buildLogin();
}
private void buildLogin()
{
Panel panel1 = new Panel();
Controls.Add(panel1);
//But then, there is no way to do this:
// if (button1.IsDisposed == true) //because of the panel, or smthing
Button button1 = new Button();
panel1.Controls.Add(button1);
button1.Click += (s, f) => { panel1.Dispose(); buildMainMenu(); };
}
private void buildMainMenu()
{
Panel panel2 = new Panel();
Controls.Add(panel2);
Button button2 = new Button();
panel2.Controls.Add(button2);
}
//This was created from the Designer and is class-scoped
private void btn_Frame_TSK1_Click(object sender, EventArgs e)
{
//Here, I have no access to the objets I've created programatically.
//button1.Text = "Text changed!";
}
}
If you want to make sure things are always completely dynamic and always done in the code behind, you may want to look at searching for the controls you've created in the Controls collection.
For example, make sure to give button1 an ID value (button1.ID="textUpdatedButton") that will identify it uniquely from other controls you create. Then use FindControl or search on the Controls collection to find the control with the ID you want to locate in your event handler.
//This was created from the Designer and is class-scoped
private void btn_Frame_TSK1_Click(object sender, EventArgs e)
{
Control control = this.FindControl("textUpdatedButton");
if(control != null && control is Button){
Button button1 = (Button)control;
button1.Text = "Text changed!";
}
}
Alternatively, to make things look more like a variable, you can use a Property to hide the control finding (as mentioned previously):
private Button Button1 {
get { return (Button)this.FindControl("textUpdatedButton"); }
}
//This was created from the Designer and is class-scoped
private void btn_Frame_TSK1_Click(object sender, EventArgs e)
{
if(this.Button1 != null){
this.Button1.Text = "Text changed!";
}
}
The actual implementation will vary with how you build up your controls, but essentially this approach can let you build everything dynamically in your code behind if you need to do it that way. Just remember to use identifiers to let you find things later.
Define your object at the class level, as Static. This way it will be accessible from all methods of all instances of the class(disposing an instance will not affect it).

Categories