Yapımcı: Son zamanlarda lambda ifadesi ve değişken yakalamalarla garip bir şey yaşadım. Kod, .NET 4.5 (VS2012) kullanan bir WPF/MVVM uygulamasıydı.Neden kurbayı bir alan değişkenine çağırmak zorundayım?
public class MyViewModel : ViewModelBase
{
public MyViewModel(Action menuCallback)
{
MyCommand = new RelayCommand(menuCallback);
}
public MyViewModel(Func<ViewModelBase> viewModelCreator)
// I also tried calling the other constructor, but the result was the same
// : this(() => SetMainContent(viewModelCreator())
{
Action action =() => SetMainContent(viewModelCreator());
MyCommand = new RelayCommand(action);
}
public ICommand MyCommand { get; private set; }
}
: I (bu komut sonra benim görünümünde bir menü öğesi bağlı olacağını)
Özünde bir RelayCommand
için kurmayı geri arama benim ViewModel farklı kurucular kullanıyordu, ben aşağıdaki kodu vardı ve daha sonra kullanarak yukarıdaki örneklerini oluşturdu:
// From some other viewmodel's code:
new MyViewModel(() => new SomeViewModel());
new MyViewModel(() => new SomeOtherViewModel());
Bu
sonra WPF menü bağlıydı - her menü öğesi veri bağlamında gibi bir MyViewModel örneği vardı. Garip olan şey, menülerin sadece bir kez çalıştığıydı. Hangi ürünlerden hangisini denediğime bakılmaksızın, uygunFunc<ViewModelBase>
'u arayacaktı - ama sadece bir kez. Başka bir menü öğesini veya aynı öğeyi tekrar seçmeyi denediysem
sadece çalışmamıştı. Hiçbir şey VS hata ayıklama çıktısında herhangi bir hata ile ilgili herhangi bir çıkış var ve çıktı.
Ben döngüler içinde değişken yakalar ile sorunların farkındayım, bu yüzden bu yüzden benim VM değiştirildi bu konunun ilişkili olduğunu tahmin yaptı:
public class MyViewModel : ViewModelBase
{
public MyViewModel(Action buttonCallback)
{
MyCommand = new RelayCommand(buttonCallback);
}
private Func<ViewModelBase> _creator;
public MyViewModel(Func<ViewModelBase> viewModelCreator)
{
// Store the Func<> to a field and use that in the Action lambda
_creator = viewModelCreator;
var action =() => SetMainContent(_creator());
MyCommand = new RelayCommand(action);
}
public ICommand MyCommand { get; private set; }
}
ve aynı şekilde denir. Şimdi her şey gerektiği gibi çalışır.
Sadece eğlence için, ben de MyViewModel
yapıcı uygun Action
dışında oluşturarak tüm Func<ViewModelBase>
yapıcı çalıştı:
// This code also works, even without the _creator field in MyViewModel
new MyViewModel(() => SetMainContent(new SomeViewModel()));
new MyViewModel(() => SetMainContent(new SomeOtherViewModel()));
Bu yüzden çalışma başardı, ama yine de merak ediyorum neden bunu bunun gibi çalışır. Derleyici neden kurucuda
Func<ViewModelBase>
doğru şekilde yakalamıyor? öyleyse, o zaman ilk yolu çalışmıyor sebebi aslında
viewModelCreator
değişkeni etrafında kapanış olmadığını ise
İki yaklaşım için oluşturulan IL'deki farklılıklara baktınız mı? Bazı ipuçları verebilir. – nicodemus13
"SetMainContent", "ViewModelBase" sınıfındaysa, son kod örneğindeki lambdada nasıl çalışıyorsunuz? – Pat
SetMainContent, viewmodel örneğini ana pencerenin görünüm modeline göndermek için iletileri (MVVMLight'tan) kullanır. Daha sonra, kullanıcı arayüzünde işlenen bir Content özelliğine atar. Bu sorunu gösteren daha eksiksiz bir kod örneği bulmaya çalışacağım –