2010-11-30 43 views
20

C# 'da bir WinForms uygulaması geliştiriyorum. GUI programlamasında sınırlı tecrübem var ve uçmada çok şey öğrenmek zorundayım. Bu söylüyorum, ben inşa yapıyorum.C# WinForms Model-Görünüm-Sunucusu (Pasif Görünüm)

GUI http://img227.imageshack.us/img227/1084/program0.jpg

Şimdi, ama çok kötü Özerk tasarım modelinde, zaten bir sürü iş yapmış:

aşağıdaki bağlantıda genel GUI görünüm bakınız. Projenin belli bir boyuta ulaşacağını bilemedim ve bu nedenle, bazı büyük refactoring yapmak için zamanı geldi.

GUI tasarım kalıpları hakkında çok çalışıyorum ve uygulamak istediğim model Pasif Görünüm'dür (bkz. http://martinfowler.com/eaaDev/PassiveScreen.html). Hepsini bir araya getirme konusunda yardım arıyorum.

Amaç: sol alt köşesindeki "TreeView" kullanıcı tıkladığında, "Liste" "Düzenleyici" alanını doldurabilirsiniz nesnelerin listesini görüntüler ne bağlı olarak

1). Bu nesneler bir TextBox veya DataGridView olabilir. Kullanıcı Listeyi, "Editör" de görmek istediğini seçmek için değiştirir 2) Model, esas olarak veri ve yapılandırma dosyalarına sahip bir klasördür. Belirli bir dizinde çalışan, çıktı dosyaları/klasörleri vb. Oluşturan harici bir program var. Geliştirdiğim bu program, bu nesneleri kullanıcı dostu bir şekilde etkin bir şekilde yönetmek/yapılandırmak üzere tasarlanmıştır

3) Sorun, Ben bir şeyleri yapıyordum test etmek imkansız olduğunu ve dolayısıyla MVP-esque Passive View tasarım desen

harekete geçmek için bu programın bağımsız olarak çalışmasını sağlamak için yapmaya çalışıyorum. Pasif Görünüm deseni ile daha karmaşık ve etkileşimli bir görünümün kullanıldığı herhangi bir örnek bulamadım.

Sorular:

1) tüm sonra TreeView her biri için alt arayüzleri/alt görüşlerini uygulamak, programın "bakmak", Editör, Kaydedici için büyük bir arayüz/görünümü uygulamak gerekir mi , vb.? Ya da bunu yapmak için daha iyi bir "yapı" var mı? 2) Görüntülemeden Sunum Yapan Kişi/Denetleyici'ye ("Pasif Görünüm tasarım desenini kullanmak istediğiniz terminoloji") ne zaman "teslim" söz konusuysa, bunu yapmamın yolu nedir? Bazen güncellenmesi gereken basit özelliklere sahibim ve bazen bir dizi adım atmam gerekiyor.

Bu konuyla ilgili önerileri ve önerileri çok isterim. İnterneti araştırdım ve bu projeye devam etmeme yardımcı olacak yeterli örnek bulamadım.

Şimdiden teşekkürler! İşte Daniel

cevap

18

MVP tasarım kalıbı kullanarak pasif görünümleri kavramını gösteren basit bir örnektir. Pasif görüşler kullandığımız için görüşün sunucunun bilgisi yoktur. Sunum yapan kişi, görüntü tarafından yayınlanan etkinliklere abone olacak ve buna göre hareket edecektir. Başlamak için bizim görüşümüz için bir sözleşme tanımlamamız gerekir. Bu genellikle bir arayüz kullanılarak elde edilir, aslında, bizim görüşümüzle çok gevşek bir bağlantıya sahip olmak istiyoruz.Farklı görünümlere veya etkinliğe geçme yeteneğinin birim testi için sahte görünümler oluşturmasını istiyoruz. İşte

müşteri BİLGİLERİ

public interface ICustomerManagementView 
{ 
    void InitializeCustomers(ICustomer[] customers); 
    void DisplayCustomer(ICustomer customer); 
    event EventHandler<EventArgs<ICustomer>> SelectedCustomerChanged; 
} 

Bizim modelinden nesnelerle görüşümüzü başlatmak için kullanılacak InitializeCustomers tek yöntemini açığa görüntülemek için kullanılacak basit bir görünüm tanımlayan bir sözleşmedir.

Ayrıca, sunumda bir işlemin gerçekleştiğine dair bildirim almak için sunucumuz tarafından kullanılacak SelectedCustomerChanged numaralı bir etkinliğimiz de var.

Sözleşmemize sahip olduğumuzda, bu etkileşimleri işlemcimizle başlatabiliriz. Bizim görünümü ve biz gerekebilir herhangi bir model sınıflarına erişim sağlamak için dependency injection adlı başka tasarım deseni kullanabilirsiniz sunucu olarak

public class CustomerManagementPresenter 
{ 
    private ICustomer _selectedCustomer; 
    private readonly ICustomerManagementView _managementView; 
    private readonly ICustomerRepository _customerRepository; 

    public CustomerManagementPresenter(ICustomerManagementView managementView, ICustomerRepository customerRepository) 
    { 
     _managementView = managementView; 
     _managementView.SelectedCustomerChanged += this.SelectedCustomerChanged; 

     _customerRepository = customerRepository; 

     _managementView.InitializeCustomers(_customerRepository.FetchCustomers()); 
    } 

    private void SelectedCustomerChanged(object sender, EventArgs<ICustomer> args) 
    { 
     // Perform some logic here to update the view 
     if(_selectedCustomer != args.Value) 
     { 
      _selectedCustomer = args.Value; 
      _managementView.DisplayCustomer(_selectedCustomer); 
     } 
    } 
} 

. Bu örnekte müşteri detaylarını almaktan sorumlu bir Müşteri Sorumluluğum var.

Kurucuda, iki önemli kod satırımız var, ilk önce görünümümüzde SelectedCustomerChanged olayına abone olduk, ilişkili eylemleri gerçekleştirebilmemiz için buradayız. İkincisi, depodan veri ile InitilaizeCustomers denedik.

Bu noktada, bizim görüşümüz için somut bir uygulama tanımlamadık, tek yapmamız gereken, ICustomerManagementView uygulayan bir nesne oluşturmak. Biz görüşümüzü alay ve bazı iddiaların gerçekleştirebilir sunumumuz mantığı test etmek istedim Bir Windows Forms uygulamasında Örneğin şu

public partial class CustomerManagementView : Form, ICustomerManagementView 
{ 
    public CustomerManagementView() 
    { 
     this.InitializeComponents(); 
    } 

    public void InitializeCustomers(ICustomer[] customers) 
    { 
     // Populate the tree view with customer details 
    } 

    public void DisplayCustomer(ICustomer customer) 
    { 
     // Display the customer... 
    } 

    // Event handler that responds to node selection 
    private void CustomerTreeViewAfterSelect(object sender, TreeViewEventArgs e) 
    { 
     var customer = e.Node.Tag as ICustomer; 
     if(customer != null) 
     { 
      this.OnSelectedCustomerChanged(new EventArgs<ICustomer>(customer)); 
     } 
    } 

    // Protected method so that we can raise our event 
    protected virtual void OnSelectedCustomerChanged(EventArgs<ICustomer> args) 
    { 
     var eventHandler = this.SelectedCustomerChanged; 
     if(eventHandler != null) 
     { 
      eventHandler.Invoke(this, args); 
     } 
    } 

    // Our view will raise an event each time the selected customer changes 
    public event EventHandler<EventArgs<ICustomer>> SelectedCustomerChanged; 
} 

yapabilirsiniz.

DÜZENLEME: Dahil özel etkinlik args

public class EventArgs<T> : EventArgs 
{ 
    private readonly T _value; 

    public EventArgs(T value) 
    { 
     _value = value; 
    } 

    public T Value 
    { 
     get { return _value; } 
    } 
} 
+0

Bilgilendirici yanıtı takdir ediyorum, ancak özellikle sorularımı yanıtlıyor. Bir Görünüm kullanmalı mıyım (bu 4-5 alt bileşenlerle etkileşime girebilir) veya Görünümler içinde Görünümler olmalıdır (arayüzler içindeki arayüzler)? Ayrıca, Görüntülemeden Sunum Yapan Olayların “dağıtılmasından” hala emin değilim ve yine de View'un Modeli nasıl gözlemlediğine dair bir açıklamaya ihtiyacım var. Programın da "yapısı" ile ilgili endişelerim var. –

+1

Özellikle yeniden kullanımını teşvik etmek istiyorsanız, daha küçük bileşenlere ayırmayı tercih ediyorum.Tek bir amacı olan, ancak birleşik kullanıcı arabirimi oluşturmak için birlikte kullanılabilen görünümler oluşturun. –

+0

Ayrıca, sunucu yapıcıya bakarsanız, olayları olaydan nasıl ele alacağınızı görebilirsiniz. –

0

Ben kendi hediyelerle ayrı görünümlerde bunları yıkmak ve hepsini arasındaki mesaj heyeti yönetmek için bir "kontrol" sunum/görünüm kullanmak. Bu yardım deneyi sadece değil, aynı zamanda kontrollerinizin de SRP'yi yerine getirmesini sağlayacak.

Yani sizin durumunuzda sonra bir ana pencere uygulayacak IFormManager ve bir IFileManager, sahip olabilir ILoggerWindow vs vs

overkill biraz kullanmak olabilir, ancak ben var tavsiye ediyor Akıllı Müşteri Yazılım Fabrikası'na (Microsoft Kalıpları ve Uygulamaları ekibinden) bir bakış - aktif olarak geliştirilmiyor, ancak MVP'nin iyi bir uygulamasına sahip ve bu tür bir görünüm kompozisyonunu oldukça iyi yapıyor. fikirler.

+0

Giriş için teşekkürler. Fakat bireysel kontrolleri nereye koyacağım? Ana görüşte? Ama ana görünümü hafifçe ilk etapta tutmaya çalışıyorum. –

+0

Sorduğum şeyi detaylandıran bir resim buldum. Bu grafiğin problemimi çözmek için yeterli olacağını düşünüyor musunuz? http://www.diskordia.ch/blog/wp-content/uploads/2009/03/subview.png –

+0

Çocuk görüşlerini ana görünümün içine koymanızı engelleyecek hiçbir şey yok - ana görünümünüz mantıksal olarak hafif, yani tek başına Sorumluluk, mesajların düzenini görüşlerin arasında paylaşmalarını sağlamaktır; onlar hakkında hiçbir şey kontrol etmezdi. –

İlgili konular