2016-08-30 3 views
1

3 View/ViewModels (현재까지!) 프로젝트가 있습니다. 그래서 나는 ListViewMainView에 각각 표시하고 사용자가 선택할 수 있습니다. 그래서 내가 이런 걸 사용 :(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> 

을 그리고 OBVListView에 바인딩. 그러나 ListView에 변화의 selectedItem가는,이 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); 
    } 
    . 
    . 
    . 
} 

을하지만 그렇지!

업데이트 : 로케이터에 대해 전혀 몰라요!

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 여전히 이전과 동일 : 그럼이 코드를 다른 클래스 이름 로케이터를 추가! 그러나

<!--<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}}"> 
. 
. 
. 

을 여전히 이전과는 다른 ViewModels에 대한 MainViewModel 거기는 때마다 다시로드있어 :이 내 XAML을 변경 않았다!

+0

1 : 변화 사이에서 살아 남기 일부 XAML을 보여 주어야하시기 바랍니다. 둘째, 관련 코드를 보여줍니다. 그 행동은 붙여 넣은 예제로 아무런 재현 할 수 없다. – lokusking

+0

나 자신의 질문에 답했다.^^ – ChenChi

+0

@lokusking MainView에 xaml을 추가했다. 실제로 중요하지 않은 다른 것들! :) – Mostafa

답변

0

예, VM의 "싱글 톤"을 만들거나 대부분의 MVVM 프레임 워크에서 제공하는 것과 같은 Locator을 사용할 수 있습니다. (기본적으로 정말 똑같습니다 ...). 내가 당신을 연결할 수 있는지 보자

...

글쎄, 내 내 ... 당신은 무엇을 알고있다. 로케이터에 대한 자세한 내용은 have a look at this answer

거의.당신은 같은 것을 원하는 :

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

이 방법은, 한 번 인스턴스를 만들을, 만 요청하는 경우, 그들은,

+0

감사합니다. 나는 이것이 어떻게 작동하는지 정확하게 이해할 수 없다. Si 당신이 그것을보고 무엇을해야하는지 말해 줄 수 있다면 내 포스트를 업데이트했다! – Mostafa

+0

이것은 처음에 내가 쓴 것과 같습니다. 그건 로케이터라고? : D – Mostafa

+0

종류. 여기에 또 다른 테이크가 있습니다 : [moah loKator !!] (https://johnpapa.net/simple-viewmodel-locator-for-mvvm-the-patients-have-left-the-asylum/) – Noctis