2014-09-12 70 views
1

我正在使用框架Catel,并且我有一个ViewControl,它由一个项目源提供的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视图模型。它将模型作为命令参数传递,以便您可以在命令中将其用作参数。

+0

谢谢吉尔特。工作!这是一个非常准确的答案。再次感谢。 – 2014-09-12 16:26:43

0

我会在VM订阅的模型上创建一个事件。我通常有一个OnPropertyChanged事件(或类似的东西),它会冒泡。

因此,该模型可能会有诸如:

public event PropertyChangedEventHandler PropertyChanged; 

而视图模型将签署这样的:

/// <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可能提供了这种开箱即用功能 - 请参见propertychangedpropertychangedadvanced

0

您的命令ShowAnotherWindow肯定要留在视图模型中。

在你UserControl添加RelativeSource这样的:

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

,并与你有什么(WindowUserControl)更换yourRootTagHere

然后,您将能够从当前视图模型创建其他视图模型(CompletePlotViewModel)。