Paweł Borawski

Paweł Borawski Student, Uniwersytet
w Białymstoku

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

Witam!
Jako, że ostatnio widać wysyp tematów dotyczących MVVM ja również dodam jeden od siebie. Otóż, zaczynam przygodę z tym wzorcem i jako pierwszego tutoriala używam tego oto linku:
Tutotrial od MS.

Otóż problem polega na implementacji interfejsu INotifyPropertyChanged.
Implementuje go w następujący sposób: http://pastebin.com/ph3LGR3m .
Zaś błędy, które występują podczas budowania: http://pastebin.com/sYaRm11d .

Ma ktoś jakieś pomysły?

Błąd był w deklaracji:
public event ProgressChangedEventHandler PropertyChanged;


Powinno być:
public event PropertyChangedEventHandler PropertyChanged;


Jeśli komuś zawracam gitarę z góry przepraszam. Temat do usunięcia.Paweł Borawski edytował(a) ten post dnia 29.11.12 o godzinie 00:18
Marcin S.

Marcin S. Programista, trener
i konsultant w
zakresie .NET/.NET
Cor...

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

Nie mam czasu analizować twojego kodu, ale proponuję zastosować od razu porządne rozwiązanie:

1. Utworzyć klasę bazową w której będziesz miał obsłużoną notyfikację, a wszystkie twoje ViewModel będą po niej dziedziczyć.


public abstract class ViewModelBase : INotifyPropertyChanged
{
protected ViewModelBase()
{
}

public event PropertyChangedEventHandler PropertyChanged;

protected void RaisePropertyChanged(string propertyName)
{
if (PropertyChanged != null)
PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
}


protected string GetPropertyName<TProperty>(Expression<Func<TProperty>> property)
{
var lambda = (LambdaExpression)property;

MemberExpression memberExpression;
if (lambda.Body is UnaryExpression)
{
var unaryExpression = (UnaryExpression)lambda.Body;
memberExpression = (MemberExpression)unaryExpression.Operand;
}
else
memberExpression = (MemberExpression)lambda.Body;

return memberExpression.Member.Name;
}

public void NotifyOfPropertyChange<TProperty>(Expression<Func<TProperty>> property)
{
RaisePropertyChanged(GetPropertyName(property));
}

#region OnPropertyChanged
/// <summary>
/// Triggers the PropertyChanged event.
/// </summary>
protected virtual void OnPropertyChanged(PropertyChangedEventArgs ea)
{
if (PropertyChanged != null)
PropertyChanged(this, ea);
}
#endregion





2. Wysyłać notyfikacje z użyciem wyrażeń lambda. Dzięki temu unikniesz błędów w literówkach.


private string _CustomerName;
/// <summary>
/// Nazwa klienta
/// </summary>
public string CustomerName
{
get { return _CustomerName; }
set
{
_CustomerName = value;
NotifyOfPropertyChange(() => CustomerName);
}
}

Paweł Borawski

Paweł Borawski Student, Uniwersytet
w Białymstoku

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

Dzięki, być może skorzystam jednak błąd znalazłem sam. "Poprostu" jakoś mnie olśniło. A z wskazówki skorzystam.
Marcin S.

Marcin S. Programista, trener
i konsultant w
zakresie .NET/.NET
Cor...

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

Jeśli używasz .NET 4.5 i C# 5.0 to możesz to jeszcze bardziej uprościć.
Paweł Borawski

Paweł Borawski Student, Uniwersytet
w Białymstoku

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

To znaczy? Używam lecz pewnie nie w dostateczny sposób. Jakieś wskazówki?

konto usunięte

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

Paweł Borawski:
To znaczy? Używam lecz pewnie nie w dostateczny sposób. Jakieś wskazówki?
Prawdopodobnie chodzi o to:
http://www.pzielinski.com/?p=1147
Marcin S.

Marcin S. Programista, trener
i konsultant w
zakresie .NET/.NET
Cor...

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

Tak, dokładnie. Miałem na myśli CallerMemberName, dodane w .NET 4.5

Dzięki temu nie trzeba w setterze podawać już nazwy właściwości, gdyż można ją pobrać za pomocą CallerMemberName.


private string _name;

public string Name
{
get { return _name; }
set
{
_name = value;
RaisePropertyChanged();
}
}



Implementacja:



private void RaisePropertyChanged(
[CallerMemberName] string caller = "" )
{
if (PropertyChanged != null)
{
PropertyChanged( this, new PropertyChangedEventArgs( caller ) );
}
}



na podst.
http://jesseliberty.com/2012/06/28/c-5making-inotifypr...
Paweł Paluch

Paweł Paluch Software Developer

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

Można to jeszcze bardziej uprościć, używając Postsharp (bądź innego AOP), by w samej propercji co raz nie wpisywać wywołań RaisePropertyChanged()

przykłądy dla Postsharp
dla całej klasy: http://www.sharpcrafters.com/solutions/notifypropertyc...

per propercja:

[Serializable]
[MulticastAttributeUsage(MulticastTargets.Property)]
public class PropertyChangedAttribute : LocationInterceptionAspect, IInstanceScopedAspect
{
[ImportMember("RaisePropertyChanged", IsRequired = true)]
public Action<string> RaisePropertyChangedMethod;

public override void OnSetValue(LocationInterceptionArgs args)
{
if (args.Value == args.GetCurrentValue())
return;

args.ProceedSetValue();

}

public object CreateInstance(AdviceArgs adviceArgs)
{
return this.MemberwiseClone();
}

public void RuntimeInitializeInstance()
{
}

}

i użycie

class Example : Microsoft.Practices.Prism.ViewModel.NotificationObject
{
[PropertyChanged]
public int SomeProp { get; set; }

}
Marcin S.

Marcin S. Programista, trener
i konsultant w
zakresie .NET/.NET
Cor...

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

Paweł Paluch:
Można to jeszcze bardziej uprościć, używając Postsharp (bądź innego AOP), by w samej propercji co raz nie wpisywać wywołań RaisePropertyChanged()

A co w sytuacji gdy zmiana jednego atrybutu ma powiadomić kilka innych atrybutów?
Mam myśli przypadek gdy od tego atrybutu są zależne inne atrybuty, np. pola obliczeniowe.
Paweł Paluch

Paweł Paluch Software Developer

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

Marcin Sulecki:
Paweł Paluch:
Można to jeszcze bardziej uprościć, używając Postsharp (bądź innego AOP), by w samej propercji co raz nie wpisywać wywołań RaisePropertyChanged()

A co w sytuacji gdy zmiana jednego atrybutu ma powiadomić kilka innych atrybutów?
Mam myśli przypadek gdy od tego atrybutu są zależne inne atrybuty, np. pola obliczeniowe.

z małą zmianą:

[Serializable]
[MulticastAttributeUsage(MulticastTargets.Property)]
public class PropertyChangedAttribute : LocationInterceptionAspect, IInstanceScopedAspect
{
[ImportMember("RaisePropertyChanged", IsRequired = true)]
public Action<string> RaisePropertyChangedMethod;

public override void OnSetValue(LocationInterceptionArgs args)
{
if (args.Value == args.GetCurrentValue())
return;

args.ProceedSetValue();

RaisePropertyChangedMethod(args.LocationName);
if (ToRaise != null)
{
foreach (var item in ToRaise)
{
RaisePropertyChangedMethod(item);
}
}

}

public object CreateInstance(AdviceArgs adviceArgs)
{
return this.MemberwiseClone();
}

public void RuntimeInitializeInstance()
{
}

public string[] ToRaise { get; set; }
}
class Example : Microsoft.Practices.Prism.ViewModel.NotificationObject
{
[PropertyChanged(ToRaise=new string[]{"PropA", "PropB"})]
public int SomeProp { get; set; }
...
}
Paweł Leśnikowski

Paweł Leśnikowski Senior Software
Developer

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

Paweł Paluch:
Można to jeszcze bardziej uprościć, używając Postsharp (bądź innego AOP), by w samej propercji co raz nie wpisywać wywołań RaisePropertyChanged()

A jak ktoś nie ma Postsharp'a to można użyć Mono.Cecil:
http://www.limilabs.com/blog/inotifypropertychanged-wi...
Marcin S.

Marcin S. Programista, trener
i konsultant w
zakresie .NET/.NET
Cor...

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

A co sądzicie o notify property weaver?
http://visualstudiogallery.msdn.microsoft.com/bd351303...
Paweł Paluch

Paweł Paluch Software Developer

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

@Paweł
dobrze widzę, że to będzie compile-waveing?

@Marcin
nie korzystałem ale wygląda przystępnie, pytanie jak to jest z konfiguracją?

moim wyborem w tej chwili jest Postsharp, chyba, że pojawi się coś jeszcze lepszego, gdyż np. w połączeniu z porządnym IoC daje duże pole do popisu.
Paweł Leśnikowski

Paweł Leśnikowski Senior Software
Developer

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

Paweł Paluch:
@Paweł
dobrze widzę, że to będzie compile-waveing?

Tak, ale oczywiście PostSharp jest lepszy.
Andrzej Szymczak

Andrzej Szymczak Student, Poznańska
Wyższa Szkoła
Biznesu i Języków
Obcych

Temat: Kolejne pytanie o MVVM. Błędy przy budowaniu.

Dorzucę swoje 3 grosze.

Na wstępie to bym odradzał .net 4.5, gdyż nie wspiera xp, także jeżeli baza klientów na xp jest duża, to może się nie opłacać.

Chyba, że zmusimy wszystkich na minimum vistę, 7, 8 lub sami zaczniemy kombinować ze środowiskiem w VM, bo innej opcji nie ma, tak czy siak albo obciążymy siebie albo użytkowników.

Co do MVVM to ja korzystam z GalaSoft - MVVM Light Toolkit i sobie chwalę, tam jest snippet od tego i po prostu podajemy sami nazwę.

Może to i półśrodek, ale lepsze niż ekspresja, a CallerMemberName też nie jest idealne, raz, że .net 4.5, dwa, że nie zawsze się sprawdza.

Wolę jednak w kodzie mieć to co napiszę, niż generowane w post, nie znoszę nawet najmniejszej przerwy po kompilacji.

Jednak nie ma to jak na sztywno mieć skompilowane, a z GalaSoft mvvm to jest naprawdę bezbolesne.

Następna dyskusja:

pytanie do programistów




Wyślij zaproszenie do