2010-02-10 26 views
6

dự án WPF của tôi sẽ được tổ chức như thế này:tách màn hình mà không cần dây ma thuật

Screens 
    Group1 
     Screen1 
     View.xaml 
     ViewModel.cs 
    Group2 
     Screen2 
     View.xaml 
     ViewModel.cs 

Để hiển thị Screen1 từ Screen2 tôi sẽ sử dụng một cái gì đó như thế này: ScreenManager.Show("Group1.Screen1") này ngoại hình (sử dụng phản ánh) trong Screens.Group1.Screen1 không gian tên cho một View và một ViewModel và instantiates chúng.

Làm cách nào để loại bỏ chuỗi ma thuật mà không cần ghép nối Screen1Screen2 (Tôi không muốn các lớp trong Screen2 sử dụng không gian tên Screen1). Ngoài ra, tôi muốn một số loại khám phá màn hình (autocompletion/intellisense)

Hoặc có thể một số cách (tự động kiểm tra) để xác minh rằng tất cả các cuộc gọi đến ScreenManager.Show đều hợp lệ.

Cập nhật: tôi đến với điều này:

public class ScreenNames 
{ 
    public Group1Screens Group1; 

    public class Group1Screens 
    { 
     public ScreenName Screen1; 
    } 
} 

public sealed class ScreenName 
{ 
    private ScreenName() { } 
} 

public class ScreenManager : IScreenManager 
{ 
    public void Show(Expression<Func<ScreenNames, ScreenName>> x) {} 
} 

Cách sử dụng:

screenManager.Show(x=>x.Group1.Screen1); 

Không lý tưởng nhưng tôi giả sử vi phạm DRY vẫn là tốt hơn so với dây ma thuật. Và tôi có thể tự động kiểm tra (với sự phản ánh) rằng tất cả các cuộc gọi là hợp lệ.

+0

Tại sao Screen2 cần biết về Screen1? Trình quản lý màn hình có tồn tại bên ngoài mỗi màn hình không? Và bởi Intellisense, bạn đang nói rằng trong quá trình phát triển bạn muốn có mỗi tên của màn hình xuất hiện trong droplist khi bạn bắt đầu gõ ScreenManager.Show()? Danh sách các màn hình tĩnh hay động (tải tại thời gian chạy)? – Dave

+0

Cuối cùng tôi sẽ pas một tham số; ScreenManager sẽ là một thuộc tính của ViewModel; Đối với intellisense tôi nghĩ rằng một danh sách tĩnh là phải:/ Tôi nghĩ rằng tôi có thể có một cái gì đó như thế này: ScreenManager.Show (x => x.Group1.Screen1) –

+0

sử dụng như ScreenManager.Show (x => x.Group1.Screen1) sẽ có nghĩa là tôi sẽ phải giữ và duy trì một danh sách riêng biệt của màn hình nhưng tôi nghĩ rằng không có cách nào khác nếu tôi muốn intellisense –

Trả lời

3

Bạn không cần tất cả công cụ ScreenManager trong WPF, vì công cụ DataTemplate có thể xử lý việc này cho bạn với đánh dấu thuần túy.

Bạn chỉ có thể databind một khu vực cụ thể của ứng dụng của bạn với một ContentPresenter và một loạt DataTemplates. Liên kết khu vực với một thuộc tính của một ViewModel 'gốc', và để cho 'root' ViewModel thực hiện INotifyPropertyChanged để WPF biết nếu bạn thay đổi ViewModel trong khu vực đó.

public class RootViewModel : INotifyPropertyChanged 
{ 
    public object Screen1ViewModel { get; } 

    public object Screen2ViewModel { get; } 
} 

DataBind kiểm soát một ContentPresenter đến tài sản sử dụng

<ContentControl Content="{Binding Path=Screen1ViewModel}" /> 

và tương tự cho người tiếp theo Screen1ViewModel. Khi bạn cần thay đổi nội dung của Screen1, bạn chỉ cần gán lại Screen1ViewModel từ mã, và vì sự kiện PropertyChanged được nâng lên, WPF sẽ chọn nó và liên kết ViewModel mới với một khung nhìn mới.

Các DataTemplates có thể đơn giản như thế này:

<Window.Resources> 
    <DataTemplate DataType="{x:Type foo:MyViewModel}"> 
     <self:MyControl /> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type foo:MyOtherViewModel}"> 
     <self:MyOtherControl /> 
    </DataTemplate> 
</Window.Resources> 

Trong trường hợp bạn không quen thuộc với nó, this article on MVVM in WPF là một giới thiệu tuyệt vời.

+0

Cảm ơn câu trả lời của bạn, tôi không chắc chắn hoàn toàn hiểu nhưng nó stil không trả lời cho câu hỏi của tôi: làm thế nào để giữ cho ViewModel của decoupled? Tôi không muốn Screen2 ViewModel trực tiếp sử dụng Screen1 –

+0

@Mark: Tôi thích cách tiếp cận này rất nhiều, nhưng tôi không chắc đây có phải là Catalin hay không. Nó gần như âm thanh với tôi như anh ta muốn thực hiện chuyển hướng các loại và có thể đi từ trang này sang trang khác. Nếu tôi hiểu cách tiếp cận của bạn, bạn đề nghị chuyển đổi viewmodel qua databinding, điều này thực sự tuyệt vời, nhưng tôi không biết đó có phải là những gì anh ta muốn hay không. BTW, bạn có thể giới thiệu bất kỳ đọc trực tuyến tốt nào mà đi qua các ví dụ mà bạn muốn thay đổi ViewModels? Tôi luôn có mối quan hệ 1: 1: 1 giữa View: ViewModel: Model và không bao giờ thay đổi ViewModel (vì tôi không biết lợi thế của nó). – Dave

+0

@Catalin DICU: Trong mô hình này, Screen1ViewModel không biết gì về Screen2ViewModel và ngược lại. RootViewModel rõ ràng biết về cả hai, nhưng lưu ý rằng cả hai thuộc tính được khai báo là kiểu System.Object, biểu thị rằng chúng thực sự có thể là bất kỳ thứ gì. Nếu bạn không muốn hardwire kiến ​​thức về các loại máy ảo vào RootViewModel, bạn có thể sử dụng DI để tiêm các máy ảo vào RootViewModel. Điều này sẽ cho nó một hàm tạo như 'RootViewModel (đối tượng vm1, object vm2)'. –

Các vấn đề liên quan