Binding to an array of structs in WPF - wpf

In my application I store an array of structs containing how much bills/coins i need to pay to a client and how many I effectively pay.
public struct MoneyType
{ //contains more, but left out for readability
public int Requested { get; set; } // How many are requested for a payment
public int Paid { get; set; } //bills paid to the customer
}
I made an array with these which I make accessible to the viewmodel in the following way:
MoneyType[] money; //correctly initialised in the constructor
public MoneyType[] GetMoney()
{
return money;
}
In the viewmodel itself I make these accessible in this way:
public MoneyType[] MoneyTypes //Denominations
{
get
{
return _dataService.GetMoney();
}
}
Finally, in my XAML, I accessed these as:
<cbtn:BillCounter x:Name="euro200" Value = "{Binding MoneyTypes[2].Paid, Mode=TwoWay }" />
The [2] is used to indicate which type of bills/coins I want to use.
I want to make this work 2 ways, so that my custom control can update the amount of coins/bills paid. For which I would need a setter for my MoneyTypes property.
I'm not sure the right way to do this. I have a feeling that somehow, I should not pass the entire array from my viewmodel/model, but a specific part of one of my MoneyTypes (the paid/requested fields, with some kind of index indicating which entry to use)
I'm unsure of how to do this.

May this answer is helps you - https://stackoverflow.com/a/7714924/3207043
Based on this, you need to use reference data types to bindings.

Related

Fill a combobox in WPF with a list of web services

I have a control like this:
<ComboBox x:Name="ComboTipo"
Height="23"
SelectionChanged="ComboTipo_SelectionChanged"
Width="450"
Canvas.Left="609"
Canvas.Top="26" />
And my code is:
ComboTipo.DisplayMemberPath = "Descripcion";
ComboTipo.SelectedValuePath = "IdTipoPersona";
ComboTipo.ItemsSource = myWebServices.dameTipos();
My web services returns a list for this object, this class is created in automatic when i add the reference to the web services:
public partial class TipoPersona {
private short idTipoPersonaField;
private string descripcionField;
/// <comentarios/>
public short IdTipoPersona {
get {
return this.idTipoPersonaField;
}
set {
this.idTipoPersonaField = value;
}
}
/// <comentarios/>
public string Descripcion {
get {
return this.descripcionField;
}
set {
this.descripcionField = value;
}
}
}
But the problem is:
The combobox displays the data types for each element of the list, and i want display the Descripcion.
Can you help me plis! Thanks
What does IdTipoPersona look like? Is it a class you created? If so, you may need to reference the property that you want displayed. It would look something like this:
ComboTipoPersona.SelectedValuePath = "IdTipoPersona.Text";
Where Text would be replaced by the property. It is really hard to judge otherwise what is going on with knowing a little more about the object structure that myWebServices.dameTipos() returns.
EDIT
Ok I was able to simulate your problem and simulate a solution as well.
Your issue is in the Tipos class. There are a couple of things necessary when binding to a combobox with a custom class.
First off, you will want to add accessors and mutators (getters and setters) to IdTippoPersona and Descripcion.
You should add a constructor that assigns to those properties with parameters.
It is usually a good idea to add a default constructor.
The finished code will look like this:
public class Tipos
{
public int IdTipoPersona { get; set; }
public string Descripcion { get; set; }
public Tipos(int id, string descripcion)
{
IdTipoPersona = id;
Descripcion = descripcion;
}
}
I found the asnwer if someone needs it.
We need create a class intermediate class but we were working with entity framework, for this way, we need add the intermediate class like complex type in my model (entity framework).
And also we need override this class.
And it works so well.
Thanks for all #Goody

c# returning arrays via properties

Id like to firstly apologise for what may appear to be a stupid question but im confused regarding the following.
Im writting a class library which will not be running on the UI thread. Inside the CL i need an array which im going populate with data received from a stored procedure call. I then need to pass this data back to the UI thread via an event.
Originally i was going to write the following.
public class ColumnInformation
{
public string[] columnHeaderNames;
public string[] columnDataTypes;
}
but im pretty sure that would be frowned upon and i instead should be using properties.
public class ColumnInformation
{
public string[] columnHeaderNames {get; set;}
public string[] columnDataTypes {get; set;}
}
but then i came across the following.
MSDN
so am i correct in assuming that i should actually declare this as follows:
public class ColumnInformation
{
private string[] _columnHeaderNames;
public Names(string[] headerNames)
{
_columnHeaderNames = headerNames;
}
public string[] GetNames()
{
// Need to return a clone of the array so that consumers
// of this library cannot change its contents
return (string[])_columnHeaderNames.Clone();
}
}
Thanks for your time.
If your concern is the guideline CA1819: Properties should not return arrays,
It will be same whether you are exposing Array as a Public Field, or Property (making readonly does not matter here). Once your original Array is exposed, its content can be modified.
To avoid this, as the link suggest, make Field private, and return Clone from the Getter.
However major concern is that there may be multiple copies of your array if retrieved many times. It is not good for performance and synchronization.
Better solution is ReadOnlyCollection.
Using ReadOnlyCollection, you can expose the collection as read only which cannot be modified. Also any changes to underlying collection will be reflected.

Value Object and View Model Property

I am working on a solution that used DDD for architecture. I have a property in my ViewModel which points to a ValueObject, the view model also implements INotifyPropertyChanged interface. The value of the ValueObject will change as a user enters data on the front end. The problem I am running into is the value object is suppose to be immutable. How can I work around this issue? Thank you in advance.
If you can edit something, then there must be a mutable container for the immutable value. Therefore, your viewmodel should act on the mutable container rather than on the immutable value directly.
An integer is an example of such an immutable value object: the Int32 type does not have any members that allow you to change the state of the object. You can only replace an integer, not change it. So a view model for an integer would look like this:
public MutableIntegerViewModel
{
private readonly mutableInteger;
public MutableIntegerViewModel(MutableInteger mutableInteger)
{
this.mutableInteger = mutableInteger;
}
public string DisplayText
{
get
{
return this.mutableInteger.Value.ToString(
CultureInfo.CurrentCulture);
}
set
{
this.mutableInteger.Value =
Int32.Parse(value, CultureInfo.CurrentCulture);
}
}
}
Where MutableInteger is just this:
public class MutableInteger
{
public int Value { get; set; }
}
I've omitted error handling and change notification here, but hopefully you get the idea.
Also note this example is not really different from the typical example of a Customer class with a FirstName and a LastName. Strings are also immutable, so again we have a mutable container for immutable values.

What should Binding Path property be set to?

Assuming I have this struct definition in C#:
public struct TimeSlotInfo
{
public int TimeSlotID;
public int StartMin;
public int CalcGridColumn;
public string BackgroundCol;
public bool ToDisable;
}
And I have a linq query as so:
var TimeSlotsInfo =
from ts in datacon.TimeSlots
select new TimeSlotInfo
{
TimeSlotID = ts.TimeSlotID,
StartMin = ts.StartMin,
CalcGridColumn = CalcTimeSlotGridColumn(ts.StartMin),
BackgroundCol = ts.ColorName,
ToDisable = false
};
If i set the ItemsSource property of say a ListBox as below:
lstBox.ItemsSource = TimeSlotsInfo;
Now, how do i set a binding path to reference the "BackgroundCol" field from the above query result?
I've tried {Binding Path=TimeSlotInfo.BackgroundCol}, {Binding Path=TimeSlotInfo/BackgroundCol}, and finally {Binding Path=BackgroundCol}...none of them seem to be working..
Can anyone help? I've tried to simplify the example as possible. Hope my problem is clear enough.
Thanks in advance.
The last one is correct ({Binding Path=BackgroundCol}) - however, you can't bind to fields, you can only bind to Properties. Define your class to be:
class TimeslotInfo {
public int TimeslotId {get; set;}
/* Etc... */
}
Not only should you use properties for binding as Paul says, but in general you should avoid public fields in the first place.
In addition, this doesn't feel like it should be a struct - do you really want value-type semantics? When in doubt, you should default to creating classes in C# - it's pretty rare that you really want a struct.
Finally, even if you did want a struct, you should almost always make structs immutable. You're almost certain to have unexpected results from mutable structs. It's all well defined and for good reasons, but it's probably not the behaviour you expect. Mutable structs are evil.
If you want your items to display whatever is stored in BackgroundCol, you can just set the DisplayMemberPath property on your ListBox to "BackgroundCol". If this isn't what you're trying to achieve, please be more specific.
Hope this helps!!

Winforms: access class properties throughout application

I know this must be an age-old, tired question, but I cant seem to find anything thru my trusty friend (aka Google).
I have a .net 3.5 c# winforms app, that presents a user with a login form on application startup. After a successful login, I want to run off to the DB, pull in some user-specific data and hold them (in properties) in a class called AppCurrentUser.cs, that can thereafer be accessed across all classes in the assembly - the purpose here being that I can fill some properties with a once-off data read, instead of making a call to the DB everytime I need to. In a web app, I would usually use Session variables, and I know that the concept of that does not exist in WinForms.
The class structure resembles the following:
public class AppCurrentUser {
public AppCurrentUser() { }
public Guid UserName { get; set; }
public List<string> Roles { get; set; }
public string Firstname { get; set; }
public string Lastname { get; set; }
}
Now, I have some options that I need some expert advice on:
Being a "dumb" class, I should make the properties non-static, instantiate the class and then set the properties...but then I will only be able to access that instance from within the class that it was created in, right?
Logically, I believe that these properties should be static as I will only be using the class once throughout the application (and not creating new instances of it), and it's property values will be "reset" on application close. (If I create an instance of it, I can dispose of it on application close)
How should I structure my class and how do I access its properties across all classes in my assembly? I really would appreciate your honest and valued advice on this!!
Thanks!
Use the singleton pattern here:
public class AppUser
{
private static _current = null;
public static AppUser Current
{
get { return = _current; }
}
public static void Init()
{
if (_current == null)
{
_current = new AppUser();
// Load everything from the DB.
// Name = Dd.GetName();
}
}
public string Name { get; private set; }
}
// App startup.
AppUser.Init();
// Now any form / class / whatever can simply do:
var name = AppUser.Current.Name;
Now the "static" things are thread-unsafe. I'll leave it as an exercise of the reader to figure out how to properly use the lock() syntax to make it thread-safe. You should also handle the case if the Current property is accessed before the call to Init.
It depends on how you setup your architecture. If you're doing all your business logic code inside the actual form (e.g. coupling it to the UI), then you probably want to pass user information in as a parameter when you make a form, then keep a reference to it from within that form. In other words, you'd be implementing a Singleton pattern.
You could also use Dependency Injection, so that every time you request the user object, the dependency injection framework (like StructureMap) will provide you with the right object. -- you could probably use it like a session variable since you'll be working in a stateful environment.
The correct place to store this type of information is in a custom implementation of IIdentity. Any information that you need to identify a user or his access rights can be stored in that object, which is then associated with the current thread and can be queried from the current thread whenever needed.
This principal is illustrated in Rocky Lhotka's CLSA books, or google winforms custom identity.
I'm not convinced this is the right way but you could do something like this (seems to be what you're asking for anyway):
public class Sessions
{
// Variables
private static string _Username;
// properties
public static string Username
{
get
{
return _Username;
}
set
{
_Username = value;
}
}
}
in case the c# is wrong...i'm a vb.net developer...
then you'd just use Sessions.USername etc etc

Resources