|
Thank you for the answer.
It looks like I am still missing something, I got the error that my list doesn't exist in the current context in the main window.
Is something more supposed to be in the "..." place in your snippet?
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
Beton B20 = new Beton();
B20.Nazwa = "C16/20 (B20)";
B20.Fck = 20;
Beton B25 = new Beton();
B25.Nazwa = "C20/25 (B25)";
B25.Fck = 25;
Beton B30 = new Beton();
B30.Nazwa = "C25/30 (B30)";
B30.Fck = 25;
Beton B37 = new Beton();
B37.Nazwa = "C30/37 (B37)";
B37.Fck = 37;
BetonCombo.ItemsSource = comboBoxList;
public class Beton
{
public string Label { get; set; }
public double Fck { get; set; }
public double Fcm { get; set; }
public double Fctm { get; set; }
public double Ecm { get; set; }
private static List<Beton> comboBoxList = new List<Beton>();
public Beton()
{
comboBoxList.Add(this);
}
}
|
|
|
|
|
That's because it's a part of the Beton class, not the MainWindow class.
If you want to access the collection, then I'd provide a get-only property (or a GetAll method) which returns a copy of the list as part of the Beton Class:
public class Beton
{
public static List<Beton> All
{ get { return new List<Beton>(all);} }
...
} That way, the outside world can't mess with your collection!
Sent from my Amstrad PC 1640
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
modified 4-Aug-18 10:09am.
|
|
|
|
|
I tried to get this to work, but I had to give up after like 3 hours.
For now I left a manually declared list after instantiating the class.
In general I got the "cannot implicitly convert Beton to String", or "Beton to Int", or "List<string> to string", etc, whie trying different ways of writing this.
I don't really know what should be the output of using class name as the List Type (as in List < Beton>) and adding .Add(This) to it. Is it supposed to add every property of the instantiated class as an object regardless of its type to the List?
I am looking for some good toutorial about types accepted by the List object, etc. Is there something you could recommend? For now I didn't find anything thorough enough.
Anyway, thanks for posting, I will do some more search on it in free time.
modified 4-Aug-18 18:17pm.
|
|
|
|
|
C# is a "strongly typed language": it doesn't try to do (most) conversions for you, and if a List contains Beton objects, then accessing the collection returns an instance of a Beton, not the individual properties of that class.
Think of it this way: A Car Park contains instances of Cars, each located in a specific bay. If you model that, then the CarPark object is a Collection of ParkingSpaces each of which can contain a single Car:
public class Car
{
public string Registration { get; set; }
public Color Color { get; set; }
}
public class ParkingSpace
{
public Car Car { get; set; }
public int Level { get; set; }
public int Row { get; set; }
public int Column { get; set; }
}
...
List<ParkingSpace> carPark = new List<ParkingSpace>();
...
foreach (ParkingSpace ps in carPark)
{
Car c = ps.Car;
Console.WriteLine("{0} is a {1} car, on floor {2}, Row {3}, Bay {4}.",
c.Registration,
c.Color,
ps.Level,
ps.Row,
ps.Column);
} You can drive a car away and park a new one in the same space without changing the collection, or the actual spaces - you just set the new value of the ParkingSpace.Car property.
Sent from my Amstrad PC 1640
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
Thank you, it works perfectly well now, it just cut like 20% of my code
The only thing left for me is to properly assing the scope for variables and collections.
I can't access my collections in the event handlers in main.
I tried to just set them to public or to make a new list with a {get} setting that returns them, but none of that works for me.
What is generally the best way to make variables and collections availible to all scopes in main window? Should I try to do it with the {get} settings on all variables and collections?
|
|
|
|
|
Look at the example I gave you for the All property, and it's static - which means you access it with just the class name from anywhere in your code that can access the Beton class:
List<Beton> allInstances = Beton.All; And it returns you a copy of the current collection.
Don't make the "raw" collection public - that lets the outside world remove instances which is a bad idea!
Sent from my Amstrad PC 1640
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
OriginalGriff wrote: Don't make the "raw" collection public - that lets the outside world remove instances which is a bad idea! List(T).AsReadOnly Method (System.Collections.Generic)[^]
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Good idea. Possibly a little advanced for the OP though!
Sent from my Amstrad PC 1640
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
I already abstained from suggesting an interface to an abstract beton-class called concrete.
..and then implementing a concrete concrete
Bastard Programmer from Hell
If you can't read my code, try converting it here[^]
"If you just follow the bacon Eddy, wherever it leads you, then you won't have to think about politics." -- Some Bell.
|
|
|
|
|
Why is this code not working?
I am trying to set a {get} property to return a copy of any list.
Just so that I would understand how this syntax is supposed to work.
To me this code looks exactly the same as in every toutorial on the internet.
namespace WpfApp5
{
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
string a = "aaaaaa";
string b = "bbbbbb";
List<string> ab = new List<string>
{
a,
b
};
public List<string> Ab
{ get { return new List<string>(ab); } }
}
}
}
and it returns error that "ab" doesn't exist in the current context in the {get} line...
this also doesn't work:
public List<string> Ab
{ get { return ab; } }
modified 6-Aug-18 15:26pm.
|
|
|
|
|
Because it genuinely doesn't exist.
You can't just go copying code from the internet - you have to understand this stuff!
When you write this:
return new List<string>(ab); The compiler looks for a variable called "ab" in the current scope - which in this case means the class MainWindow and doesn;t find it. Since it can't find anything to use to initialise the collection, it complains.
And yes, I know you wrote this:
List<string> ab = new List<string>
{
a,
b
}; earlier - but that's a local variable - it's scope is limited to the closest pair of curly brackets:
public void MyMethod(string a}
{
Console.WriteLine(a);
{
string b = "hello";
Console.WriteLine(a);
Console.WriteLine(b);
if (a == "World")
{
string c = "!";
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
}
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
}
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
}
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
public void MyOtherMethod()
{
Console.WriteLine(a);
Console.WriteLine(b);
Console.WriteLine(c);
}
Sent from my Amstrad PC 1640
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
ok, but after ab I also defined a public variable Ab (the capital A) that was supposed to give access to a private variable ab through the get accessor isn't it?
The whole problem here is how to access a variable out of it's scope. I dont know how to do it. I thought the get accessor is supposed to do that, but it's in the curly brackets, so does it mean it's also out of scope........?
If methods have curly brackets, classes have curly brackets, and accessors have curly brackets, then how do I ever access my variable out of scope without defining it as public ?
|
|
|
|
|
|
The property is self contained - it can't access local variables (i.e. variables which are declared within the scope of a method) because they only exist for the lifetime of the method - when the method returns, the variable is genuinely destroyed and no longer exists to be accessed!
Your property can only access variables which are scoped to the class, so they are either static (in which case there is only one for all instances of the class) or they are declared public , private , protected , internal , or protected internal - none of which can be applied to local variables.
Local variables are held on something called the stack, which is part of the thread that does the actual execution, not as part of the class instance.
Sent from my Amstrad PC 1640
Bad command or file name. Bad, bad command! Sit! Stay! Staaaay...
AntiTwitter: @DalekDave is now a follower!
|
|
|
|
|
OriginalGriff wrote: public , private , protected , internal , or protected internal
Don't forget the new private protected[^] option.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Thank you all for help, everything worked out, I just had to sit through some toutorials, books and webpages. The program is finished and it's all looking very pretty and realiable.
Now though, I have a very annoying thing about C# to complain about, and I need to ask for some tip on how to handle it properly using some good C# practices...
I have a lot of arithmetic calculations to be solved in the program, and they return wrong values if I don't explicitly specify that a number 2 is a double and not an integer...... For example:
double number = (double) 6 / (double) 10;
box_d.Text = number.ToString("F3") + " cm";
double number = 6 / 10;
box_d.Text = number.ToString("F3") + " cm";
and on top of that, all future calculations based on this result are also wrong, it's not the fault of the ToString() method. The variable is just wrong!
I mean... I don't mind parsing values like 0.5 as 0.500000019747272 etc. But Having 6/10 display as 0 instead of 0.6 is just so stupid, is there any logical reason for it to be like this? I understand that the program is trying to fit the result into an integer, but I explicitly state that my result must be double... I thought it's supposed to reduce the amount of memory used by the program if I set such simple numbers as integers, but if this kind of errors occur, is it even worth it? What is the good practice to work around this thing?
Should I never define any simple numbers like "2" or "8" as integers but use only "double" for everything?
modified 19-Aug-18 9:58am.
|
|
|
|
|
The problem you have is that you're dividing two integers, so the result will be truncated to an integer before the result is stored in your variable.
Only one of the casts is unnecessary; if either the numerator or denominator is a floating-point type, the other will be converted to that type before the division takes place.
You can simplify your code by using a numeric suffix:
However, if you want an integer number to be treated as double, use the suffix d or D, for example:
double x = 3D;
So in your example:
double number = 6D / 10D;
There are other suffixes you can use to denote other numeric types:
C# - Numeric Suffixes - Stack Overflow[^]
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Hi all friends,
I have a Model which is needed to have different validation attributes assigned to it in different Conditions, I don't have to create multiple classes for different attributes, because the same model class is being used in multiple post methods.
Following is my class:
public class ServiceFunctionCategoryLKP
{
public int Id { get; set; }
[Required(ErrorMessage = "Code is required.")]
[StringLength(2, MinimumLength = 2, ErrorMessage = "The field {0} length must be at least 2.")]
public string Code { get; set; }
[Required(ErrorMessage = "Description is required.")]
public string Description { get; set; }
public string ServiceFunctionCategoryCode { get; set; }
[Required(ErrorMessage = "ModeOfServiceCode is required.")]
public string ModeOfServiceCode { get; set; }
public string ModeOfServiceDescription { get; set; }
public int CodeLenth {get; set;}
}
StringLength attribute should be different for different calls, is there any way I can have set it differently or dynamically depending upon the input object of the action method. Means I have a field in my input object as above called CodeLength, depending upon this field I have to change the StringLength attributes MinimumLength and Error message properties dynamically, it means in every different Post call, it could be different depending upon the CodeLength field value.
If I have tried in the following way, with IsValid method, problem is how would I know CodeLength field (that is coming as a property of Object in action method) within IsValid method to compare the length of the field with CodeLength field.
public override bool IsValid(object value)
{
int num = (value == null) ? 0 : ((string)value).Length;
return value == null || (num >= this.MinimumLength && num <= this.MaximumLength);
}
Any help would be greatly greatly helpful, thanks in advance friends.
Thanks,
Abdul Aleem
"There is already enough hatred in the world lets spread love, compassion and affection."
-- modified 3-Aug-18 14:31pm.
|
|
|
|
|
"Baked in" at compile time, apparently.
Might try overriding the properties in question with a derived class for each of the "different conditions".
"(I) am amazed to see myself here rather than there ... now rather than then".
― Blaise Pascal
|
|
|
|
|
can you please give me some example or something please?
Thanks,
Abdul Aleem
"There is already enough hatred in the world lets spread love, compassion and affection."
|
|
|
|
|
Not easily, but it can be done.
You're going to need to create a custom DataAnnotationsModelValidatorProvider , and modify the rules it returns.
validation - Possible to change Data Annotations during Runtime? (ASP.NET MVC's [Range] [Required] [StringLength] etc.) - Stack Overflow[^]
Eg:
public class CustomModelValidatorProvider : DataAnnotationsModelValidatorProvider
{
protected override IEnumerable<ModelValidator> GetValidators(ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
if (metadata.Model is ServiceFunctionCategoryLKP model && metadata.PropertyName == nameof(model.Code) && model.CodeLength >= 0)
{
var newAttributes = new List<Attribute>(attributes);
var stringLength = newAttributes.OfType<StringLengthAttribute>().FirstOrDefault();
if (stringLength != null)
{
newAttributes.Remove(stringLength);
if (model.CodeLength != 0)
{
newAttributes.Add(new StringLengthAttribute(model.CodeLength)
{
MinimumLength = model.CodeLength,
ErrorMessage = $"The field {{0}} length must be at least {model.CodeLength}."
});
}
attributes = newAttributes;
}
}
return base.GetValidators(metadata, context, attributes);
}
} Register in Globals.asax.cs :
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add( new CustomValidatorProvider() );
NB: You're effectively allowing the user to override the validation rule by modifying a hidden field on the page. As a result, the validation can't really be trusted.
It would be better to create a separate model class for each required code length.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Just checking, is it going to remove all the other Validations that I have put on other classes?
Thanks,
Abdul Aleem
"There is already enough hatred in the world lets spread love, compassion and affection."
|
|
|
|
|
No. It checks that the instance being validated is the specific model class; that the property being validated is the Code property; and it only replaces the StringLength validator on that property.
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|
Hi Richard,
One last thing, I have created the method in the following way:
public class CustomModelValidatorProvider : System.Web.Mvc.DataAnnotationsModelValidatorProvider
{
protected override IEnumerable<System.Web.Mvc.ModelValidator> GetValidators(System.Web.Mvc.ModelMetadata metadata, ControllerContext context, IEnumerable<Attribute> attributes)
{
if (metadata.Model is LookupTable)
{
LookupTable model = metadata.Model as LookupTable;
if (metadata.PropertyName == GetPropertyName(() => model.CodeLength) && (model.CodeLength > 0))
{
var newAttributes = new List<Attribute>(attributes);
var stringLength = newAttributes.OfType<StringLengthAttribute>().FirstOrDefault();
if (stringLength != null)
{
newAttributes.Remove(stringLength);
if (model.CodeLength != 0)
{
newAttributes.Add(new StringLengthAttribute(model.CodeLength)
{
MinimumLength = model.CodeLength,
ErrorMessage = @"The field {{0}} length must be at least {model.CodeLength}."
});
}
attributes = newAttributes;
}
}
}
return base.GetValidators(metadata, context, attributes);
}
public string GetPropertyName<T>(Expression<Func<T>> propertyLambda)
{
var me = propertyLambda.Body as MemberExpression;
if (me == null)
{
throw new ArgumentException("You must pass a lambda of the form: '() => Class.Property' or '() => object.Property'");
}
return me.Member.Name;
}
}
can you please let me know how can I decorate or use it on my Model class, can you please give me that example, I am asking this question because this value is coming as null: metadata.PropertyName, so I am not able to compare with property name. So any help please?
thank you very very much buddy - as I said earlier have a Wonderful weekend with family and friends buddy.
Thanks,
Abdul Aleem
"There is already enough hatred in the world lets spread love, compassion and affection."
-- modified 3-Aug-18 19:53pm.
|
|
|
|
|
You register the provider in Global.asax.cs :
ModelValidatorProviders.Providers.Clear();
ModelValidatorProviders.Providers.Add( new CustomValidatorProvider() );
I'd expect to see the PropertyName set to null for the class-level validation, but I'd expect the method to be called again for each property on the class.
You're currently checking whether the validators are for the CodeLength property; you need to customise the validators for the Code property instead.
if (metadata.PropertyName == GetPropertyName(() => model.Code) && ...
"These people looked deep within my soul and assigned me a number based on the order in which I joined."
- Homer
|
|
|
|
|