Compare value member when setting property - c#

I have a property, of a custom class, in C# that I have overridden the setter for. I want to compare a property of/in the custom class in the setter, like the following:
public DatabaseInfo CurrentDatabaseManagedSelection
{
get { return CurrentDatabaseManaged; }
set {
if (String.Equals(value.Name, CurrentDatabaseManaged.Name,StringComparison.OrdinalIgnoreCase))
return;
CurrentDatabaseManaged = DatabaseManagement.ReadDatabase(value.FileName);
}
}
Inside the DatabaseInfo class, there is a standard String property called Name.
However, when I run the program I get the following exception. Can anyone tell me why this happens and how to solve the issue please?
Exception has been thrown by the target of an invocation.
EDIT: I do set the value of the property which the setter above is for, in the constructor of the view model. I do this simply by setting CurrentDatabaseManagedSelection equal to an object of the DatabaseInfo class.

Think I might have found the problem... Well, I've solved it!
The issue was CurrentDatabaseManaged had not been initialized and so was equal to null when I tried setting the above property. I discovered this by adding a try.. catch in the setter method, and created a new String for CurrentDatabaseManaged.Name - the stack trace pointed to that line.
Hope that helps some one else in the future.

Related

How to fix 'Remove property setter' build error?

I have a property in a model which has auto property getter and setter:
[DataMember]
public Collection<DTOObjects> CollectionName { get; set; }
I get the following error when building the solution:
Microsoft.Usage : Change 'propertyname' to be read-only by removing the property setter.
However, when I remove the setter and run the code, an error occurs because it's trying to set the property! It appears it's asking me to remove the setter despite the fact it is being set somewhere in the code.
Has anyone else come accross this problem? What do I need to modify?
I'm going to guess this is a list/collection (or something similar), in which case yes - it is unusual to have a setter. A typical example might be:
private readonly List<Foo> items = new List<Foo>();
public List<Foo> Items { get { return items; } }
Most callers should not be trying to assign to that; they shouldn't need to - they can add/remove/enumerate/clear/etc the list without ever needing to assign it.
an error occurs because it's trying to set the property
Then consider changing that code so that it doesn't try to set the property. It should not need to in virtually all cases.
One solution is to initialize the Collection in the constructor...
public class Email
{
public Email()
{
To = new List<MailAddress>();
}
....
public List<MailAddress> To { get; }
}
Then just use .add in code:
Email oEmail = new Email();
oEmail.To.Add(new MailAddress("Foo#fighter.com", "Mr. Foo"));
Just suppress it, right click the error and click suppress in code & an attribute will be added to the property.
Generally you shouldn't have a public set for collections as this allows the list to be replaced, however with objects that are created or deserialized at runtime sometimes the public setter is necessary.
From the docs:
"You can suppress the warning if the property is part of a Data Transfer Object (DTO) class. Otherwise, do not suppress warnings from this rule."
If it's not part of a DTO:
"To fix a violation of this rule, make the property read-only. If the design requires it, add methods to clear and repopulate the collection."
The preferred manner of replacing a read-only collection property is to use the Clear and AddRange methods (or their equivalents).
https://learn.microsoft.com/en-us/visualstudio/code-quality/ca2227?view=vs-2019

Use a property in a constructor of an object fails

I have a class defined like this:
class TouchScreenDisabledGrid:DataGrid,INotifyPropertyChanged
I want to change soome of my class behaviour depanding on it's properties, that are set threw the xaml when using it in a window.
For example the following:
<my:TouchScreenDisabledGrid x:Name="dataGridView" Tag="13" />
Will cause an exception if In my constructor I try to check this value:
public TouchScreenDisabledGrid(){
Console.WriteLine(this.Tag.ToString());
}
Why is that and how can I check the propery and use it?
Objects defined in XAML are constructed using the default constructor and then their properties are set. So imagine that this:
<my:TouchScreenDisabledGrid x:Name="dataGridView" Tag="13" />
Is the moral equivalent of this:
var g = new TouchScreenDisabledGrid();
g.Name = "dataGridView";
g.Tag = "13";
It should now be obvious why Tag is null inside your constructor, hence you are getting a NullReferenceException when you call ToString().
Continuing further, you cannot use the classical model of doing something inside the constructor that depends on object properties being set. You have to find another way of achieving your goal -- what way, depends on what exactly the goal is (for example you can use INotifyPropertyChanged to detect that a property has been set; or you can listen to an event that triggers later in the lifetime of the visual and fetch the values from there).
If the property is set in XAML it will not be set in the constructor. Use OnLoaded override to do this.

C# - Check which event changed / accessed a Property

I have a class with property say
private string fieldSelectedItem;
public string FieldSelectedItem
{
get
{
return fieldSelectedItem;
}
set
{
fieldSelectedItem = value;
}
}
it is accessed from many place.
I came across a situation that the a property in class is accessed by some event. and also some event is changing the value. i tried debugging. is it possible to check which event/function has changed/accessed the property. is there any method to do so.
How about placing a breakpoint in the setter and looking at the stack trace.
Simples.
The stack trace should give you some information about where the call has come from, if you break in the property accessors.

OneWay binding on WinForms?

I have a control with a property public MyClass MyProperty{...} which value is shown on the screen as a graph. I want this property to be bindable to any other MyClass in the program by using the Binding class (MyProperty would be the propertyName parameter in this Binding constructor, and the other MyClass would be the dataMember parameter) .
MyClass implements INotifyPropertyChanged so on that side everything is all right. But it happens that if I don't implement a get accessor in MyProperty and try to bind something to it, I get a "Cannot bind to the property 'MyProperty' on the target control.
Parameter name: PropertyName" error.
Does this mean I have to implement a get accessor even if I know I will never need to read it's value and I want a OneWay (source to target) binding, and even if I just return null in the get accessor?
I'm guessing the Binding class uses this to compare the new value to the old one or to do some other internal stuff. I'm not sure, then, if it's a good idea to just return null, or it would be better to keep always a copy of whatever last object was assigned with the set accessor and return it in the get accessor. Maybe I really don't even need to write a get accessor and I'm doing something else wrong. It just happens that I get the error only when I comment out the get accessor and stop getting it when I put it back.
Edit: In case there is any confusion: When I say MyProperty's value is shown on the screen as a graph I don't mean it has a value that some other code reads and show in the screen. No one reads any value from MyProperty. MyProperty's set accessor is the one that draws stuff on the screen and that's the end of the cycle.
I'm not 100% sure I understand what you mean, but I think the exception you're encountering stems from the Binding class's CheckBinding function (reflectored):
if (descriptor.IsReadOnly && (this.controlUpdateMode != ControlUpdateMode.Never))
{
throw new ArgumentException(SR.GetString("ListBindingBindPropertyReadOnly", new object[] { this.propertyName }), "PropertyName");
}
Therefore, changing the Binding's ControlUpdateMode to ControlUpdateMode.Never may be what you're looking for

Fixing .NET code generation of properties for user controls

I have a property of type IEnumerable<SomeClassIWrote> in a user control. When I use this control in a GUI, the .Designer.cs file contains the line:
theObject.TheProperty = new SomeClassIWrote[0];
Which for some reason causes a compiler warning:
Object of type 'SomeClassIWrote[]' cannot be converted to type
'System.Collections.Generic.IEnumerable`1[SomeClassIWrote]'.
Which is a mystery to me because I pass arrays as IEnumerables all the time, and the compiler has never complained.
For what it's worth, I have a default value of null specified for the property, but I got the same error before I set a default value.
How can I fix this so Visual Studio doesn't complain and ask me to ignore and continue every time I pull up the designer?
Code for the property:
[DefaultValue(null)]
public IEnumerable<SomeClassIWrote> TheProperty {
get {
return _theProperty;
}
set {
if (value == null) {
_theProperty = new SomeClassIWrote[] { };
}
else {
_theProperty = value;
}
}
}
First up, do you WANT to be able to set it in the designer?
If not, add the following attributes:
[Browsable(false)]
[DesignerSerializationVisibility(DesignerSerializationVisibility.Hidden)]
If you DO want to set in the designer, I'd start out by trying your class as a SomeClassIWrote[], to see if that works.
That aside, is it that important to use an IEnumerable here? As you say, you can pass arrays as IEnumerables.
I suspect there's probably some restrictions inside the designer, which wiser people than me know about...
And if you really DO want an IEnumerable property, you can expose your array as an IEnumerable, but keep your array as a designer-friendly backing field.

Categories