2014-09-12 2 views
1

Я использую фреймворк Catel, и у меня есть View с TabControl, который питается источником товаров. TabContent был сделан с Datatemplate, и внутри него есть команды. Одна из этих команд должна открыть новое окно, отображающее содержимое из TabContent.Создание ViewModel из модели

Что я пытаюсь сделать? Я размещаю команду, чтобы открыть новое окно в модели (потому что из DataTemplate вы находитесь в контексте модели). Команда вызывается правильно, однако я не могу ссылаться на объект ViewModel из моей модели.

Я напишу здесь короткую версию моего кода, чтобы лучше показать проблему.

на мой взгляд:

... 
<TabControl Grid.Column="2" ItemsSource="{Binding Plots}" > 
    ... 
    <views:TabContent.Template> 
     <DataTemplate> 
      <Grid> 
       ... 
        <DockPanel Grid.Column="0"> 
         <ToolBarTray DockPanel.Dock="Left" Orientation="Vertical"> 
          <ToolBar> 
           <Button Command="{Binding ShowAnotherWindow}"> 
            <Image Source="{StaticResource GalleryPropertyImage}" /> 
           </Button> 
          </ToolBar> 
         </ToolBarTray> 
        </DockPanel> 

       ... 
      </Grid> 
     </DataTemplate> 
    </views:TabContent.Template> 
</TabControl> 
... 

И в моей модели у меня есть команда ShowAnotherWindow, которая выполняется, но я не могу сделать что-то вроде:

CompletePlotViewModel viewModel = new CompletePlotViewModel(this); 

Что вы посоветуете мне делать?

ответ

0

Несмотря на то, что контекст привязки является моделью в шаблоне данных, по-прежнему очень неправильно вводить команды внутри модели. Они должны жить в модели представления.

Что вы можете сделать это:

<TabControl x:Name="tabControl" Grid.Column="2" ItemsSource="{Binding Plots}" > 

Затем вы можете использовать эту привязку:

<views:TabContent.Template> 
    <DataTemplate> 
     <Grid> 
      ... 
       <DockPanel Grid.Column="0"> 
        <ToolBarTray DockPanel.Dock="Left" Orientation="Vertical"> 
         <ToolBar> 
          <Button Command="{Binding ElementName=tabControl, Path=DataContext.ShowAnotherWindow}" CommandParameter="{Binding }"> 
           <Image Source="{StaticResource GalleryPropertyImage}" /> 
          </Button> 
         </ToolBar> 
        </ToolBarTray> 
       </DockPanel> 

      ... 
     </Grid> 
    </DataTemplate> 
</views:TabContent.Template> 

Как вы можете видеть это сейчас связывается с ShowAnotherWindow на ViewModel. Он передает модель в качестве параметра команды, поэтому вы можете использовать это как параметр в своей команде.

+0

Спасибо, Герт. работал!! Это был очень точный ответ. Еще раз спасибо. –

0

Я бы создал событие на модели, на которую подписывается VM. Обычно у меня есть событие OnPropertyChanged (или что-то в этом роде), которое пузырится вверх.

Таким образом, модель может иметь что-то вроде:

public event PropertyChangedEventHandler PropertyChanged; 

И в ViewModel бы подписаться так:

/// <summary> 
/// Set up property changed events. Call on initialisation 
/// </summary> 
private void SetupPropertyChanged() 
{ 
    if (Model != null) 
    { 
    Model.PropertyChanged -= Model_PropertyChanged; 
    Model.PropertyChanged += Model_PropertyChanged; 
    } 
} 


public void Model_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e) 
{ 
// do stuff here. 
} 

модели представления будут иметь доступ к модели, так что вы всегда можете манипулировать оттуда. Преимущество этого метода заключается в том, что модели не нужно знать о ее родительском объекте, просто есть событие, на которое VM может зарегистрироваться.

Другой пример здесь - https://stackoverflow.com/a/12002511/852806

ПРИМЕЧАНИЕ: Я согласен с другими ответами, что логика и данные не должны быть в том же позже. Мой ответ больше связан с изменением данных, приводящих к эффекту в виртуальной машине, что часто может быть законным.

ПРИМЕЧАНИЕ 2: Похоже, что Catel может предоставить такую ​​функциональность из коробки - см. propertychanged и propertychangedadvanced.

0

Ваша команда ShowAnotherWindow обязательно должна оставаться в режиме просмотра.

В вашей UserControl добавить RelativeSource так:

<Button Command="{Binding ShowAnotherWindow},RelativeSource={RelativeSource AncestorType={x:Type yourRootTagHere},Mode=FindAncestor}"> 

и заменить yourRootTagHere с тем, что у вас есть (или WindowUserControl).

Затем вы можете создать другую модель (CompletePlotViewModel) с текущей модели.

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