2016-08-30 2 views
1

У меня есть проект, который имеет 3 View/ViewModels (До сих пор, конечно!). Поэтому у меня есть ListView в MainView, чтобы показать каждый из них и может быть выбран пользователем. Так что я использовал что-то вроде этого:(WPF/MVVM) Отдельный экземпляр в MainViewModel

class MainViewModel :INotifyPropertyChanged 
{ 
    public ObservableCollection<BaseViewModel> obv 
    { 
     get { return this._obv; } 
    } 
    public MainViewModel() 
    { 
     pvm = new PViewModel(); 
     lvm = new LViewModel(); 
     svm = new SViewModel(); 
     cvm = new CViewModel(); 
     ivm = InstanceViewModel.Instance; 
     obv.Add(pvm); 
     obv.Add(lvm); 
     obv.Add(svm); 
    } 
    . 
    . 
    . 
} 

И это MainView:

<Window x:Class="Banking_System.MainWindow" 
    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:local="clr-namespace:Banking_System" 
    xmlns:view="clr-namespace:Banking_System.View" 
    xmlns:model="clr-namespace:Banking_System.Model" 
    xmlns:viewmodel="clr-namespace:Banking_System.ViewModel" 
    mc:Ignorable="d" 
    Title="MainWindow" Height="550" Width="1200" MinHeight="500" MinWidth="800"> 
<Window.DataContext> 
    <viewmodel:MainViewModel/> 
</Window.DataContext> 
<Window.Resources> 
    <BooleanToVisibilityConverter x:Key="boo2vis"/> 
    <DataTemplate DataType="{x:Type viewmodel:PViewModel}"> 
     <view:P/> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type viewmodel:LViewModel}"> 
     <view:L/> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type viewmodel:SViewModel}"> 
     <view:S/> 
    </DataTemplate> 
    <DataTemplate DataType="{x:Type viewmodel:CViewModel}"> 
     <view:C/> 
    </DataTemplate> 
</Window.Resources> 
<Grid FlowDirection="RightToLeft"> 
    <Grid.ColumnDefinitions> 
     <ColumnDefinition Width="30*"/> 
     <ColumnDefinition Width="100*"/> 
    </Grid.ColumnDefinitions> 
    <ListBox x:Name="ListBoxMenu" Margin="5" Grid.Column="0" ItemsSource="{Binding obv}"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <TextBlock Text="{Binding Name}" Margin="10" Padding="10"/> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 
    <Border Grid.Column="1" Margin="5" BorderBrush="#FF7F9DB9" BorderThickness="1"> 
     <ContentControl Margin="10" Content="{Binding SelectedItem, ElementName=ListBoxMenu}"/> 
    </Border> 
</Grid> 

А потом Свяжите ListView к OBV. Но после того, как делать это, когда SelectedItem в изменениях ListView, Это MainViewModel получает новый экземпляр И из-за того, что все остальные ViewModels в нем, получат новый экземпляр. (Потому что я написал new *Viewmodel() в нем!)
(в другом слове, все приложения получают обновления, как и его только что открыли!)

Q: Так есть в любом случае, чтобы предотвратить такого рода действий?
Примечания: Хотя я мог бы использовать экземпляры во все ViewModels и написать что-то вроде этого:

/* In each ViewModel have something like this */ 
public static LViewModel Instance 
    { 
     get 
     { 
      if (_Instance == null) 
       _Instance = new LViewModel(); 
      return _Instance; 
     }  
    } 


/* Then change the MainViewModel to something like this */ 

class MainViewModel :INotifyPropertyChanged 
{ 
    public ObservableCollection<BaseViewModel> obv 
    { 
     get { return this._obv; } 
    } 
    public MainViewModel() 
    { 
     pvm = PViewModel.Instance; 
     lvm = LViewModel.Instance; 
     svm = SViewModel.Instance; 
     cvm = CViewModel.Instance; 
     ivm = InstanceViewModel.Instance; 
     obv.Add(pvm); 
     obv.Add(lvm); 
     obv.Add(svm); 
    } 
    . 
    . 
    . 
} 

Но я не правильно ли это или нет!

Обновление: Я вообще не знаю о Locator! Так добавить еще одно имя класса Locator с этим кодом:

class Locator 
{ 
    public LViewModel LInstance 
    { 
     get { return new LViewModel(); } 
    } 
    public PViewModel PInstance 
    { 
     get { return new PViewModel(); } 
    } 
    public SViewModel SInstance 
    { 
     get { return new SViewModel(); } 
    } 
    public MainViewModel MainInstance 
    { 
     get { return new MainViewModel(); } 
    } 
} 

Но мой MainViewModel еще такой же, как раньше! Я изменить XAML к этому:

<!--<Window.DataContext> 
    <viewmodel:MainViewModel/> 
</Window.DataContext>--> 
. 
. 
. 
<!-- Just added the DataContext --> 
<ListBox x:Name="ListBoxMenu" Margin="5" Grid.Column="0" ItemsSource="{Binding obv}" DataContext="{Binding MainInstance, Source={StaticResource LocatorVM}}"> 
. 
. 
. 

Но все же, как и раньше, MainViewModel и там для других ViewModels получил перезагружается каждый раз!

+0

первый, показать некоторые XAML пожалуйста. 2. Покажите соответствующий код. Это поведение не может воспроизводиться с вашим вставленным примером – lokusking

+0

Я думаю, что вы ответили на свой вопрос^^ – ChenChi

+0

@lokusking Я добавил xaml для MainView. Другие не важны на самом деле! :) – Mostafa

ответ

0

Да, вам нужно либо создать «одноэлемент» ваших виртуальных машин, либо вы можете использовать Locator, как тот, который поставляется с большинством фреймворков MVVM. (что в принципе делает то же самое ...).

Давайте посмотрим, если я могу связать вас ...

Ну, мой мой ... что вы знаете. have a look at this answer для получения дополнительной информации о локаторе

Почти.Вы хотите что-то вроде:

class Locator 
{ 
    private LViewModel _lInstance; 
    public LViewModel LInstance 
    { 
     get { return _lInstance ?? (_lInstance = new LInstance()); } 
    } 
    .... 
} 

Таким образом, вы создаете экземпляр один раз, и только тогда, когда требуется, и они должны выжить между изменениями :)

+0

Спасибо! Я не мог точно понять, как это работает, я обновил свой пост, если бы вы могли взглянуть на него и сказать, что делать! – Mostafa

+0

Итак, это похоже на то, что я написал на первом месте? Это называется локатором? : D – Mostafa

+0

Kinda. вот еще один пример: [moah loKator !!] (https://johnpapa.net/simple-viewmodel-locator-for-mvvm-the-patients-have-left-the-asylum/) – Noctis

Смежные вопросы