Problem with declaring List<myClass> property in VS2010 - c#

Hi
I created two usercontrol (the line & the station) and use the STATION in THE LINE usercontrol and finally i use the "LINE" usercontrol in some forms.
There is no problem at design time, but whem i want to add "Line" usercontrol to form.
In this case, visual studio stop working and then closed.
I comment some changes in my code and find that problem is from property about number of stations in line. whem i comment it every thing go ok but i need this property.
this is my code
[Serializable]
public class ActionPoint
{
public string CarInfo;
public string RightStationName;
public string RightStationInfo;
public string LeftStationName;
public string LeftStationInfo;
public ActionPoint()
{
}
}
and use this class in my property. I use this property to define stations in line.
public class Line : UserControl
{
public List<ActionPoint> Stations
{
get { return Stations; }
set { Stations = value; }
}
}

That code is recursive (when you try to get or set that property it goes on forever - follow the code...); the IDE is probably trying to either display that in a property-grid, or write code for the designer.cs - and is hitting your friendly stack-overflow exception.
As appropriate implementation would be:
private List<ActionPoint> stations = new List<ActionPoint>();
public List<ActionPoint> Stations { get { return stations; } }

I think the problem with property, not list, try this.
List<ActionPoint> _Stations;
public List<ActionPoint> Stations
{
get { return _Stations; }
set { _Stations = value; }
}
or
public List<ActionPoint> Stations
{
get;
set;
}

Related

How to add a property to a control's DataBindings

I want to write a control derived from CheckedListBoxControl (DevExpress), and I need to add a property to the (DataBindings)
These are the standard Properties shown in the PropertyGrid:
So I can only choose between Tag and Text.
What I want is to add a third option called gttMasterField (which will be of type int, don't know if this matters)
I have been experimenting with the documentation but with no results.
These don't seem to cover exact what I am looking for, I don't know the correct search terms to find this, which makes it difficult to google for it. It will probably be somewhere in the documentation but also there I don't know on what terms to look for.
Create a Windows Forms user control that supports simple data binding
Create a Windows Forms user control that supports lookup data binding
Create a Windows Forms user control that supports complex data binding
Here is some code with comments that will also help to explain what I am searching for
public partial class gttDXManyToManyCheckedListBox : CheckedListBoxControl
{
private int _gttMasterField;
// This I want populated by setting the binding property MasterField
public int gttMasterField
{
get { return _gttMasterField; }
set { _gttMasterField = value; }
}
}
The project is a dotnet framework 4.7.2
To make a custom Property appear in the PropertyGrid's (DataBindings), decorate the Property with the BindableAttribute set to true:
[Bindable(true)]
public int gttMasterField
{
get { return _gttMasterField; }
set { _gttMasterField = value; }
}
Optionally also decorate with the desired DesignerSerializationVisibilityAttribute attribute
[Bindable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public int gttMasterField
{
get { return _gttMasterField; }
set { _gttMasterField = value; }
}
The class can also specify the default bindable Property, settings a DefaultBindingPropertyAttribute:
[DefaultBindingProperty("gttMasterField")]
public partial class gttDXManyToManyCheckedListBox : CheckedListBoxControl
{
private int _gttMasterField;
[Bindable(true)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Content)]
public int gttMasterField
{
get { return _gttMasterField; }
set { _gttMasterField = value; }
}
}
Important note:
the class should implement INotifyPropertyChanged -> a bindable Property is supposed to raise notification events. When the binding is set in the Designer, a BindingSource is generated to mediate the binding, but it requires that the objects involved send change notifications (mostrly to determine when the Property value is updated, usually as DataSourceUpdateMode.OnPropertyChanged).
For example:
using System.Runtime.CompilerServices;
[DefaultBindingProperty("gttMasterField")]
public partial class gttDXManyToManyCheckedListBox : CheckedListBoxControl, INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
private int _gttMasterField;
[Bindable(true)]
public int gttMasterField
{
get { return _gttMasterField; }
set { _gttMasterField = value; NotifyPropertyChanged(); }
}
private void NotifyPropertyChanged([CallerMemberName] string PropertyName = null)
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(PropertyName));
}
}
Setting DesignerSerializationVisibility.Content implies initialization. If a BindingSource is used, this object supports initialization on itself, the Attribute is not strictly required.
It could be set to DesignerSerializationVisibility.Hidden, though, depending on the use case.

Binding with dynamic columns to a datagrid with mvvm

So I have a WPF MVVM application with a datagrid, and I'm having some trouble setting up the datagrid. I have simplified down the model to make this easier to see the issue, but try to assume that the model can not change (unless for some reason it absolutely has to). I have an observable collection of a custom object as my item source. Let's call the object MyObject. So I have this as my datagrid's itemsource:
ObservableCollection<MyObject> myObjectCollection;
Each object contains an observable collection of another type of custom object. Let's call these new objects MyObjectElement. So each MyObject has the property:
ObservableCollection<MyObjectElement> myObjectElementCollection;
Each MyObjectElement has 3 properties:
string Name;
string Element;
bool IsField;
It can safely be assumed that each MyObject has the same number of MyObjectElements in the myObjectElementCollection, and they all have matching Name and IsField properites. I want a column for each MyObjectElement in a MyObject's myObjectElementCollection only if the IsField property is set to true. Element is the value of each cell.
Now that is the first part of the problem: getting that DataGrid to generate with support for two-way binding. The second part of this problem is the DataGrid Column Types.
I have 2 classes, MyObjectImage and MyObjectTextBox. These both inherit from MyObjectElement. The collection myObjectElementCollection in MyObject does not actually contain any MyObjectElements. It only contains MyObjectImage and MyObjectTextBox objects. If the type of of MyObjectElement is MyObjectTextBox, then it should just show the string.
However, if the type is MyObjectImage the datagrid column should show an image. MyObjectImage contains a property that is a string called ImageType. This string will always be 1 of three values: "PNG", "XAML", or "SVG". If it is equal to "PNG", it is safe to assume that Element is a base64 string of the png. If it is equal to "XAML" it is safe to assume that the image is stored as a large XAML string in Element. If it is equal to "SVG", then it is safe to assume that the image would be an svg as a string, which I do have a converter function that will turn that into a XAML string. The user would change out the image via double clicking on the cell, though that is semi-irrelevant to the problem. It is also safe to assume that the ImageType property will match with it's associated ImageTpe properties in the other myObjectElementCollections.
If you are able to input any advice to any part of this datagrid problem, that would be awesome! I've been banging my head on this for weeks! To make things a bit easier, here is some sample code of the model's structure (it is safe to assume that INotifyPropertChanged is implemented in the class ObservableObject):
My Object
public class MyObject : ObservableObject
{
private ObservableCollection<MyObjectElement> _MyObjectElements;
public ObservableCollection<MyObjectElement> MyObjectElements { get { return _MyObjectElements; } set { if (_MyObjectElements!= value) { _MyObjectElements= value; RaisePropertyChanged("MyObjectElements"); } } }
}
MyObjectElement
public class MyObjectElement : ObservableObject
{
private string _Name;
private string _Element;
private bool _IsField;
public string Name { get { return _Name; } set { if (_Name != value) { _Name = value; RaisePropertyChanged("Name"); } } }
public string Element { get { return _Element; } set { if (_Element != value) { _Element = value; RaisePropertyChanged("Element"); } } }
public bool IsField { get { return _IsField; } set { if (_IsField != value) { _IsField = value; RaisePropertyChanged("IsField"); } } }
}
MyObjectImage
public class MyObjectImage : MyObjectElement
{
private string _ImageType;
public MyObjectImage() : base()
{
}
public MyObjectImage(string name, string element, string imageType) : base(name, element)
{
ImageType = imageType;
}
public string ImageType { get { return _ImageType; } set { if (_ImageType != value) { _ImageType = value; RaisePropertyChanged("ImageType"); } } }
}
MyObjectTextBox
public class MyObjectTextBox : MyObjectElement
{
public MyObjectTextBox() : base()
{
}
public MyObjectTextBox(string name, string element) : base(name, element)
{
}
}
Again, any and all help is appreciated with this problem; Thank you!
I was able to accomplish the first part of the problem through a method that can be found here. The second part of this problem should be able to be accomplished through templating the incoming items.I can easily create an image property that does a conversion to a bitmap image from any of those as the display for the datagrid column.

Change text of Button from another form class in C#

I want to modify something in Mission Planner and I want to change button from another class/form in C# in this function :
public void CloseAllConnections()
{
myButton1.Text = "Disconnecting all";
...
}
function that is located in :
namespace MissionPlanner
{
public partial class MainV2 : Form
{
...
}
...
}
the idea is that everything works perfectly when i am focused on that menu, but sometimes i get a error
i even made a function like this
public MyButton GetMyButton1 { get { return myButton1; } }
and also created new instance
var myObject = new MainV2(true);
myObject.myButton1.Text = "Disconnecting all";
nothing works ...
i don't even know where is the function called from, because is clear that is not called from MainV2 class ...
An exception of type 'System.NullReferenceException' occurred in MissionPlanner.exe but was not handled in user code
Any ideas? Thank you.
It appears that your click event form object is called (name) myButton1, and that you are calling the following to change it: myobject.myButton1.Text = "Disconnecting all". Try using myButton1.Text = "Disconnecting all" instead.
You need to grab an instance of the form where the button resides.
Do this by saving a static reference to the form in it's constructor:
namespace MissionPlanner
{
public partial class MainV2 : Form
{
public static MainV2 CurrentForm;
public MainV2()
{
CurrentForm = this;
InitializeComponent();
}
Then somewhere else in your code:
public void CloseAllConnections()
{
MainV2.CurrentForm.myButton1.Text = "Disconnecting all";
...
}
One thing that you could try is to pass the button from the form to the class that will be modifying the button.
public class Example
{
public Button MyButton1 { get; set; }
public Example(Button myButton1)
{
MyButton1 = myButton1;
}
public void CloseAllConnections()
{
MyButton1.Text = "Disconnecting all";
}
}
This should successfully set the button's text on MainV2.
Are you using any sort of multi-threading in your app? if so:
Make sure you either only change the button from the same thread it was created by,
or simply use the ControlInstance.Invoke() method to delegate the change.

How to set CheckListBox itemsSource to all properties of a class object?

I am using WPF checkListBox And I want to populate its elements with all properties of the class given below. And I have a class named Person
namespace MyProject
{
public class Person
{
public enum PersonFields
{
PersonPermission1,
PersonPermission2,
}
bool _personPermission1;
bool _personPermission2;
public bool PersonPermission1
{
get
{
return _personPermission1;
}
set
{
if (_personPermission1!= value)
{
_personPermission1= value;
}
}
}
public bool PersonPermission2
{
get
{
return _personPermission1;
}
set
{
if (_personPermission2!= value)
{
_personPermission2= value;
}
}
}
}
}
I want to populate a checkListBox with its Properties dynamically. as in given image.
I you really want to get the names of all your properties, you can get a list of them like this:
typeof(Person).GetTypeInfo().DeclaredProperties.Select(prop => prop.Name).ToList(),
I noticed you also have a matching inner enum, so you could use its values instead:
Enum.GetNames(typeof(Person.PersonFields));
In both cases you'll still need additional code to set property values based on user actions.
I think a better approach would be to have a Dictionary of permissions:
var personPermissions = new Dictionary<Person.PersonFields, bool>
{
{ Person.PersonFields.PersonPermission1, false },
{ Person.PersonFields.PersonPermission2, false }
}
Now you could bind the Dictionary to ItemsSource, display Key and bind Value to checkbox.
Yeah I got my answer...
chkListBoxPerson.ItemsSource = typeof(Person).GetProperties();
chkListBoxPerson.DisplayMemberPath = "Name";
Here chkListBoxPerson is the name of my CheckListBox.

Editing a property of an object inside an object in PropertyGrid

I'm trying to make an object, configureable/editable with a propertygrid.
This is all going well, except for objects inside objects.
I've got an object/class named "ContactInformation". And inside that object I've got an object named "Correspondence".
This is how that part looks:
[Browsable(false)]
public Correspondence Correspondence
{
get;
set;
}
public int CorrespondenceStatus
{
get { return this.Correspondence.Status; }
set { this.Correspondence.Status = CorrespondenceStatus; }
}
public string CorrespondenceComment
{
get { return this.Correspondence.Comment; }
set { this.Correspondence.Comment = CorrespondenceComment; }
}
public DateTime CorrespondenceDate
{
get { return this.Correspondence.LastSend; }
set { this.Correspondence.LastSend = CorrespondenceDate; }
}
That way I can show the properties/variables of the object inside the object, in the propertygrid.
Anyway, when I edit the values now, and press enter, or click somewhere else, instead of keeping it the value I just typed in, it changes back..
Anyone got an idea why this is happening? Or maybe a better idea to show the properties of objects in objects in the propertygrid?
To edit properties inside an object (this is what you see for example with the winform editor with properties like Font, or Padding, ... where you can "expand" the oject clicking on the 'plus' icon) , you can use the ExpandableObjectConverter class, like this:
[TypeConverter(typeof(ExpandableObjectConverter))]
public class Correspondence
{
...
}
and remove the Browsable(false) of course:
public Correspondence Correspondence
{
get;
set;
}

Categories

Resources