2014-10-08 25 views
5

Bir UI tasarlamasına yardımcı olmak için MVVM Işık kütüphanesini kullanmaya karar verdim. Araştırma ve deneme yanılmalarından sonra, aradığım cevapları henüz bulamadım. Ben googled ve bulabildiğim her StackOverflow soru okudum, ancak benim sorunum SO üzerinde benzersiz gibi görünüyor.MVVM Light - Kullanıcı Görüntüleme Sayısı olarak denetler

Tek bir pencereye sahip bir kullanıcı arayüzü tasarlamak ve farklı Görünümler/Kullanıcı Denetimleri ile doldurmak istiyorum. UserControls arasında paylaşılan bir gezinme çubuğu istemiyorum, ne de birden çok pencerenin açılmasını istemiyorum. Her bir View/UserControl kendi ViewModel'e bağlanmalı, MainWindow bir MainViewModel'e bağlanacaktır.

Örnek senaryo - 3 UserControls

ayrıca
1. MainWindow populates with first UserControl which has a listbox and 3 buttons, the first button is enabled. 
2. User clicks the first button. 
3. MainWindow populates with second UserControl. 

Veya ile MainWindow

2. User selects choice from a listbox, button two and three become available. 
3. User clicks second/third button. 
4. MainWindow populates with second/third UserControl. 

Vb,

Belki de benim yaklaşım gerçekçi değil ama bu zorundadır hissetmek vb mümkün olmak Bu parçaların nasıl çalışacağını kavramsal olarak anlamıyorum. Benim arzularımın benzersiz bir yolu yoktur. Bunun yinelenen bir soru olduğunu düşünüyorsanız lütfen yönlendirin. Şerefe.


anlamak İşleri kolaylaştırmak için, aşağıda bazı sınıfları yer verdik. İlk olarak, benim App.xaml.

<Application x:Class="Bobcat_BETA.App" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:views="clr-namespace:Bobcat_BETA.UserControls" 
      xmlns:vm="clr-namespace:Bobcat_BETA.ViewModels" 
      StartupUri="MainWindow.xaml" 
      mc:Ignorable="d"> 
    <Application.Resources> 
     <vm:ViewModelLocator x:Key="Locator" d:IsDataSource="True" /> 

     <DataTemplate DataType="{x:Type vm:SavedScenariosViewModel}"> 
      <views:SavedScenariosUserControl /> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type vm:ScenarioEditorViewModel}"> 
      <views:ScenarioEditorUserControl /> 
     </DataTemplate> 
     <DataTemplate DataType="{x:Type vm:SimulatorViewModel}"> 
      <views:SimulatorUserControl /> 
     </DataTemplate> 

    </Application.Resources> 
</Application> 

MainWindow.xaml

<Window x:Class="Bobcat_BETA.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    Title="Bobcat - Version:0.00" 
    DataContext="{Binding Main, Source={StaticResource Locator}}"> 
<Grid> 
    <ContentControl Content="{Binding CurrentView}"/> 
</Grid> 

ViewModelLocator.cs

namespace Bobcat_BETA.ViewModels 
{ 

    public class ViewModelLocator 
    { 

     private static MainViewModel _main; 

     public ViewModelLocator() 
     { 
      _main = new MainViewModel(); 
     } 

     [System.Diagnostics.CodeAnalysis.SuppressMessage("Microsoft.Performance", 
      "CA1822:MarkMembersAsStatic", 
      Justification = "This non-static member is needed for data binding purposes.")] 
     public MainViewModel Main 
     { 
      get 
      { 
       return _main; 
      } 
     } 
    } 
} 

MainViewModel.cs

namespace Bobcat_BETA.ViewModels 
{ 
    public class MainViewModel : ViewModelBase 
    { 
     private ViewModelBase _currentViewModel; 

     readonly static SavedScenariosViewModel _savedScenarioViewModel = new SavedScenariosViewModel(); 
     readonly static ScenarioEditorViewModel _scenarioEditorViewModel = new ScenarioEditorViewModel(); 
     readonly static SimulatorViewModel _simulatorViewModel = new SimulatorViewModel(); 

     public ViewModelBase CurrentViewModel 
     { 
      get 
      { 
       return _currentViewModel; 
      } 
      set 
      { 
       if (_currentViewModel == value) 
        return; 
       _currentViewModel = value; 
       RaisePropertyChanged("CurrentViewModel"); 
      } 
     } 

     public MainViewModel() 
     { 
      CurrentViewModel = MainViewModel._savedScenarioViewModel; 
      SavedScenarioViewCommand = new RelayCommand(() => ExecuteSavedScenarioViewCommand()); 
      ScenarioEditorViewCommand = new RelayCommand(() => ExecuteScenarioEidtorViewCommand()); 
      SimulatorViewCommand = new RelayCommand(() => ExecuteSimulatorViewCommand()); 
     } 

     public ICommand SavedScenarioViewCommand { get; private set; } 
     public ICommand ScenarioEditorViewCommand { get; private set; } 
     public ICommand SimulatorViewCommand { get; private set; } 

     private void ExecuteSavedScenarioViewCommand() 
     { 
      CurrentViewModel = MainViewModel._savedScenarioViewModel; 
     } 

     private void ExecuteScenarioEidtorViewCommand() 
     { 
      CurrentViewModel = MainViewModel._scenarioEditorViewModel; 
     } 

     private void ExecuteSimulatorViewCommand() 
     { 
      CurrentViewModel = MainViewModel._simulatorViewModel; 
     } 
    } 
} 

SavedScenariosViewModel.cs

namespace Bobcat_BETA.ViewModels 
{ 
    public class SavedScenariosViewModel : ViewModelBase 
    { 

     public SavedScenariosViewModel() 
     { 
     } 

     ObservableCollection<ScenarioModel> _scenarioModels = new ObservableCollection<ScenarioModel>() 
     { 
      new ScenarioModel() {Name = "Scenario 0", ID = 000, Desc = "This will describe the Scenario Model."}, 
      new ScenarioModel() {Name = "Scenario 1", ID = 001, Desc = "This will describe the Scenario Model."}, 
      new ScenarioModel() {Name = "Scenario 2", ID = 002, Desc = "This will describe the Scenario Model."}, 
      new ScenarioModel() {Name = "Scenario 3", ID = 003, Desc = "This will describe the Scenario Model."}, 
      new ScenarioModel() {Name = "Scenario 4", ID = 004, Desc = "This will describe the Scenario Model."}, 
      new ScenarioModel() {Name = "Scenario 5", ID = 005, Desc = "This will describe the Scenario Model."}, 
      new ScenarioModel() {Name = "Scenario 6", ID = 006, Desc = "This will describe the Scenario Model."}, 
      new ScenarioModel() {Name = "Scenario 7", ID = 007, Desc = "This will describe the Scenario Model."}, 
      new ScenarioModel() {Name = "Scenario 8", ID = 008, Desc = "This will describe the Scenario Model."}, 
      new ScenarioModel() {Name = "Scenario 9", ID = 009, Desc = "This will describe the Scenario Model."} 
     }; 
     public ObservableCollection<ScenarioModel> ScenarioModels 
     { 
      get { return _scenarioModels; } 
     } 

    } 
} 

<UserControl x:Class="Bobcat_BETA.UserControls.SavedScenariosUserControl" 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
      xmlns:vm="clr-namespace:Bobcat_BETA.ViewModels" 
      mc:Ignorable="d" 
      d:DesignHeight="300" d:DesignWidth="300"> 

    <UserControl.Resources> 
     <ResourceDictionary> 
      <ResourceDictionary.MergedDictionaries> 
       <ResourceDictionary Source="/Dictionaries/MasterDictionary.xaml" /> 
      </ResourceDictionary.MergedDictionaries> 
     </ResourceDictionary> 
    </UserControl.Resources> 

    <UserControl.Style> 
     <DynamicResource ResourceKey="GeneralUserControl"/> 
    </UserControl.Style> 

    <Grid> 
     <Label Content="Saved Scenario Selection" 
       Style="{StaticResource GeneralLabel}" HorizontalAlignment="Left" Margin="26,30,0,0" VerticalAlignment="Top" Height="62" Width="345"/> 
     <Label Content="Chose Flight Model:" 
       Style="{StaticResource GeneralLabel2}" 
       HorizontalAlignment="Left" Margin="27,111,0,0" VerticalAlignment="Top" Height="43" Width="345"/> 
     <ListBox Style="{StaticResource GeneralListBox}" 
       HorizontalAlignment="Left" Height="509" Margin="27,154,0,0" VerticalAlignment="Top" Width="345" 
       ItemsSource="{Binding ScenarioModels}"/> 

     <Button Content="New" 
       Style="{StaticResource TransitionButton}" 
       HorizontalAlignment="Left" Margin="948,601,0,0" VerticalAlignment="Top" MinHeight="62" MinWidth="150" IsEnabled="True" 
       Command="{Binding ScenarioEditorViewCommand}"/> 

     <Button Content="Edit" 
       Style="{StaticResource TransitionButton}" 
       HorizontalAlignment="Left" Margin="401,519,0,0" VerticalAlignment="Top" MinHeight="62" MinWidth="150" 
       Command="{Binding SaveScenariosViewCommand}"/> 
     <Button Content="Load" 
       Style="{StaticResource TransitionButton}" 
       HorizontalAlignment="Left" Margin="401,601,0,0" VerticalAlignment="Top" MinHeight="62" MinWidth="150" 
       Command="{Binding SimulatorViewCommand}"/> 

    </Grid> 
</UserControl> 

Net olmayan SavedScenariosUserControl.xaml

, ben de Modeli sınıfları ekleyebilir, ama ne olup bittiğini çıkarımlar yapabilir varsayalım. Teşekkürler.

cevap

3

Bu nedenle, yaklaşımınız çok makul ve bu işlevselliği elde etmek için kullanmanız gereken bazı karışıklıklar var. . Tüm görünüm modellerini içeren bir "MainViewModel" kullanmak zorundaydım. Bu görünüm modelleri, veri içeriği farklı bir görünüm modeline geçtiğinde, ilgili kullanıcı kontrolünün uygun görünüme geçeceği şekilde davranır. Takip ettiğim iyi bir örnek Sheridan here tarafından cevaplandı. Uygun veri şablonları ve veri bağlam anahtarları ile app.xaml içine kanca sihirli gibi işlenecektir: D

Sheridan'ın örneğinden ayrıldığım yerdeyim (çünkü ayrı bir geçiş komutu sınıfı/nesnesi oluşturmak istemediğim için), Gerçekten de, veri kapsamımı değiştirmek için "MainViewModel" e geri mesaj gönderebilmek için görüntüleme modumdan mesajlar göndermek için mvvm ışığı (galasoft) kullandım. MVVM ışık mesajlarını kullanmanın iyi bir örneği here bulunabilir. Mesajı "çocuk" Görünüm Modelinden gönderin ve "MainViewModel" e kaydedin.

İyi şanslar!

+0

Aslında benim App.xaml'ım tam olarak bahsettiğiniz ilk örnek gibi ortaya koydu. ViewModellerimi BaseViewModel'den türetmek yerine, ViewModelBase'den MVVM Light'dan türedim. Ancak Messenger'da biraz kayboldum. Yarın tüm sınıflarımın hepsini gözden geçirmesi için göndereceğim. – piofusco

+0

Tamam! ViewModelBase'inizi MVVM Işığından nasıl aldığınız konusunda beni biraz kaybettiniz. Ama evet kodunuzu yayınlayın ve bir göz atacağım. – Stunna

+0

Yukarıda bazı kod eklendi. – piofusco

1

IChildLayout örneği için bir Arabirim kullanamaz mısınız? senin MainWindows ise her bu arayüzün miras ViewModel ...

public interface IChildLayout:INotifyPropertyChanged 
{ 
    public MainWindows_ViewModel Parent; 
} 

...

Eğer düğmelere tıkladığınızda değiştiren bir özellik IChildLayout,

...

böyle bir şey olabilir ViewModel
public class MainWindows_ViewModel:INotifyPropertyChanged 
{ 
    public MainWindows_ViewModel() 
    { 
     //Here i set the default ViewModel 
     this.Child=new First_ViewModel(){Parent=this}; 
    } 

    private IChildLayout _child; 
    public IChildLayout Child 
    { 
     get 
     { 
      return _child; 
     } 
     set 
     { 
      _child=value; 
      _child.Parent=this; 
      NotifyPropertyChanged("Child"); 
     } 
    } 
    #region INotifyPropertyChangedMembers... 
} 

Her bir düzen için ViewModel ana penceresini alabilirsiniz ("Child" özelliğini kendi ViewModel'den düzenleyerek düzeni değiştirmek önemlidir ...)

Ana pencerelerinizin içine bir UserControl koydunuz (xaml'de), İçerik Çocuk Mülkünüze Bağlandıysa, Child özelliğini değiştirdiğinizde her zaman yenilenecektir. Bu durumda

<Windows> 
    <Windows.DataContext> 
     <local:MainWindows_ViewModel/> 
    </Windows.DataContext> 
    <UserControl Content={Binding Child}> 
     <UserControl.Resources> 
      <DataTemplate DataType="{x:Type ViewModels:First_ViewModel}"> 
        <Controls:First_View DataContext="{Binding}"/> 
      </DataTemplate> 
      <DataTemplate DataType="{x:Type ViewModels:Second_ViewModel}"> 
        <Controls:Second_View DataContext="{Binding}" /> 
      </DataTemplate> 
     </UserControl.Resources> 
    </UserControl> 
</Windows> 

, senin First_ViewModel olabilir: (Bu örnekte, ben

public class First_ViewModel:IChildLayout 
{ 
public MainWindows_ViewModel Parent {get;set;} 

public ICommand cmdBtn1click{get;set;} 
private Pass_to_second_ViewModel() 
{ 
    //Here i change the Parent Child Property, it will switch to Second_View.xaml... 
    this.Parent.Child=new Second_ViewModel(); 
} 

public First_ViewModel() 
{ 
    // Here i connect the button to the command with Prism... 
    this.cmdBtn1click=new DelegateCommand(()=>Pass_to_second_ViewModel()); 

} 

#region INotifyPropertyChangedMembers... 

}

Bunun size yardımcı olacağını umuyoruz ... düğmesine eylemleri bağlamak için prizma DelegateCommand kullanmak Bir WPF uygulamasında farklı bir sekmeyi yönetmek için bu tür bir şey yaptım.

+0

Bu mantıklı ses gibi görünüyor, bu yüzden bu çalışma için elimden geleni yapacağım. Herhangi bir ek kod örneği memnuniyetle karşılanacaktır. Teşekkürler. – piofusco