martedì 26 ottobre 2010

DotNet - CollectionChanged (Workaround)

C# 4.0

Una proprietà di tipo ObservableCollection<T> ( Plus) di un oggetto (Item) per notificare l’aggiunta, la cancellazione o l’aggiornamento di un elemento deve agganciare l’evento “CollectionChanged”, quindi:

_currentItem.Plus.CollectionChanged += CurrentPlusPropertyChanged;

private void CurrentPlusPropertyChanged(object sender, NotifyCollectionChangedEventArgs e)
        {
              
        }

Si è visto però che per quanto riguarda l’aggiornamento questo evento non scatta e ad oggi non c’è una spiegazione ufficiale su questa anomalia. Bisogna quindi adottare questo workaround: agganciare l’evento PropertyChanged di ogni singolo elemento delle collection;

foreach (Plu plu in _currentItemProduct.Plus)
                    {
                        plu.PropertyChanged += CurrentPluPropertyChanged;
                    }

private void CurrentPluPropertyChanged(object sender, PropertyChangedEventArgs e)
        {
             
        }

venerdì 8 ottobre 2010

IIS 6.0 - Page not found (404)

Problema
In una macchina con Windows Server 2003 e IIS 6.0 è stato installato il framework .NET 4.0. A questo punto è stato installato un servizio WCF realizzato con VS2010 (framework 4.0) ma richiamando la pagina Service.svc si aveva sempre l’errore 404 (Page not found).

Soluzione  
Aprire la console di amministrazione di IIS 6.0 e verificare che nelle “Estensioni servizio Web”, ASP.NET 4.0 sia impostato su “Consenti”.

martedì 21 settembre 2010

WPF - Aggiungere una colonna ad una DataGrid

C# 4.0
Definita una DataGrid (grdValues) in una maschera WPF, si vuole aggiungere a run-time un’altra colonna con l’opportuno binding ed assegnando anche uno stile definito sempre nello XAML.
Si può procedere quindi nel seguente modo:
DataGridTextColumn dataGridTextColumnOtherInfo = new DataGridTextColumn();
                       
Binding binding = new Binding("OtherInfo");
dataGridTextColumnOtherInfo.Binding = binding;

// Vengono ridimensionate tutte le colonne.
grdValues.Columns[0].Width = 120;
grdValues.Columns[1].Width = 120;
dataGridTextColumnOtherInfo.Width = 120;

// Stile già definto nello XAML della view.
dataGridTextColumnOtherInfo.EditingElementStyle = (System.Windows.Style)Resources["CellEditStyle"];
dataGridTextColumnOtherInfo.Header =”Other info”;

grdValues.Columns.Add(dataGridTextColumnOtherInfo);

martedì 14 settembre 2010

Serializzare un oggetto che implementa INotifyPropertyChanged

In alcuni contesti c’è la necessità di serializzare un oggetto che implementa l’interfaccia INotifyPropertyChanged. Per fare questo quindi non basta decorare la classe con l’attributo  [Serializable], bisogna anche aggiungere l’attributo  [field: NonSerialized] all’evento PropertyChanged.

A seguire un breve esempio:

    [Serializable]
    public class Department: INotifyPropertyChanged
    {
        [field: NonSerialized]
        public event PropertyChangedEventHandler PropertyChanged;

        /// <summary>
        /// Initializes a new instance of the <see cref="Department"/> class.
        /// </summary>
        public Department()
        {
        }

          }   

giovedì 9 settembre 2010

WPF - PropertyChanged is NULL (Part II) -> Implements IEquatable<>

Riprendendo il post “WPF - PropertyChanged is NULL” c’è da aggiungere che se si va in modifica di un oggetto, dopo aver caricato una maschera WPF (binding ad una proprietà di tipo Coupon) con all’interno alcuni controlli tra i quali anche un combo, non si riesce ad impostare il combo con il valore presente nella proprietà dell’oggetto.


In pratica il combo è binding alla proprietà CouponType dell’oggetto Coupon, CouponType a sua volta ha la proprietà impostata a “ValueFree” ma questa non viene visualizzata nel combo.

Il combo ha come ItemSource una lista (CouponTypes) di oggetti di tipo CouponType, il quale oggetto a sua volta implementa l’interfaccia INotifyPropertyChanged, quindi riepilogando:
public class Coupon : INotifyPropertyChanged

{

public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged(string propertyName)

{

if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

}



private CouponType _couponType;

/// <summary>

/// "CouponType": il tipo di coupon: Unspecified, Free, ValueFree, Fidelity, Serialized;

/// </summary>

public CouponType CouponType

{

get { return _couponType; }

set

{

if (value == _couponType) return;

_couponType = value;

OnPropertyChanged("CouponType");

}

}



}





public class CouponType : INotifyPropertyChanged

{

public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged(string propertyName)

{

if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

}



/// <summary>

/// Gets or sets the code.

/// </summary>

/// <value>The code.</value>

public CouponTypeEnum Code

{

get { return _code; }

set

{

if (value == _code) return;

_code = value;

OnPropertyChanged("Code");

}

}



/// <summary>

/// Gets or sets the description.

/// </summary>

/// <value>The description.</value>

public string Description

{

get { return _description; }

set

{

if (value == _description) return;

_description = value;

OnPropertyChanged("Description");

}

}



private CouponTypeEnum _code;

private string _description;

}

Bisogna quindi, per risolvere questa anomalia, implementare l’interfaccia IEquatable<CouponType> nell’oggetto CouponType nel seguente modo:
public class CouponType : INotifyPropertyChanged, IEquatable<CouponType>

{

#region IEquatable<CouponType> Membri di

bool IEquatable<CouponType>.Equals(CouponType other)

{

if (ReferenceEquals(null, other)) return false;

if (ReferenceEquals(this, other)) return true;

return Equals(other._code, _code) && Equals(other._description, _description);

}

public static bool operator ==(CouponType first, CouponType second)
{
return Equals(first, second);
}

public static bool operator !=(CouponType first, CouponType second)
{
return !Equals(first, second);
}
#endregion
}

martedì 7 settembre 2010

WPF - Il default di un combo non viene impostato correttamente (PropertyChanged is NULL)

C# 4.0

Si verifica la seguente anomalia: dopo aver caricato una maschera WPF (binding ad una proprietà di tipo Coupon) con all’interno alcuni controlli tra i quali anche un combo, non si riesce ad impostare il combo con un determinato elemento.


Il combo ha come ItemSource una lista (CouponTypes) di oggetti di tipo CouponType, il quale oggetto a sua volta implementa l’interfaccia INotifyPropertyChanged, quindi riepilogando:


public class Coupon : INotifyPropertyChanged

{

public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged(string propertyName)

{

if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

}

private CouponType _couponType;

/// <summary>
/// "CouponType": il tipo di coupon: Unspecified, Free, ValueFree, Fidelity, Serialized;
/// </summary>

public CouponType CouponType

{

get { return _couponType; }

set

{

if (value == _couponType) return;

_couponType = value;

OnPropertyChanged("CouponType");

}

}



}


public class CouponType : INotifyPropertyChanged

{

public event PropertyChangedEventHandler PropertyChanged;

protected void OnPropertyChanged(string propertyName)

{

if (PropertyChanged != null) PropertyChanged(this, new PropertyChangedEventArgs(propertyName));

}

/// <summary>
/// Gets or sets the code.
/// </summary>
/// <value>The code.</value>

public CouponTypeEnum Code

{

get { return _code; }

set

{

if (value == _code) return;

_code = value;

OnPropertyChanged("Code");

}

}

/// <summary>
/// Gets or sets the description.
/// </summary
/// <value>The description.</value>

public string Description

{

get { return _description; }

set

{

if (value == _description) return;

_description = value;

OnPropertyChanged("Description");

}

}
private CouponTypeEnum _code;

private string _description;

}


Al caricamento della maschera si crea un nuovo oggetto di tipo Coupon e si carica la collection di _couponTypes:

_coupon = new Coupon();
_couponTypes = ContextCommonService.LoadCouponTypes();

Quindi per impostare l’elemento di default si usa la seguente lambda expression :

Coupon.CouponType = CouponTypes.Find(item => item.Code == CouponTypeEnum.ValueFree);

Il risultato è che il combo non viene impostato correttamente perché (in debug) si nota che PropertyChanged è sempre NULL.

Alla fine si è quindi capito che PRIMA bisogna caricare la collection _couponTypes e DOPO inizializzare l’oggetto Coupon:

_couponTypes = ContextCommonService.LoadCouponTypes();
_coupon = new Coupon();

venerdì 3 settembre 2010

LINQ to Entities - "L'espressione LINQ specificata contiene riferimenti a query associate a contesti diversi"

C# 4.0


Una delle possibili cause di questa eccezione è quella di inserire direttamente nella lambda expression della clausola Where un oggetto var. Per ovviare questo quindi basta assegnare il suo valore ad una variabile.


if (!string.IsNullOrEmpty(typeCode))

{

// Recupero del tipo base della promozione.

var queryType = from pt in orangeRepositoryEntities.PromotionType

where pt.Code.Equals(typeCode)

select pt.BasePromotionType;


query = query.Where(p => p.PromotionType.Contains(queryType.First()));

string basePromotionType = queryType.First();
query = query.Where(p => p.PromotionType.Contains(basePromotionType));

}



if (!string.IsNullOrEmpty(code))

query = query.Where(p => p.Code.Contains(code));

if (!string.IsNullOrEmpty(salesDriveCode))

query = query.Where(p => p.SalesDriveCode.Contains(salesDriveCode));



query = query.Where(p => p.StartValidity >= fromStartValidity.Date && p.StartValidity <= toStartDate);

query = query.Where(p => p.StopValidity >= fromStopValidity.Date && p.StopValidity <= toStopDate);



foreach (var promotion in query)

{



}