从模型创建ViewModel

时间:2014-09-12 15:13:56

标签: c# wpf mvvm catel

我正在使用框架Catel,我有一个带有TabControl的View,它由一个itemsource提供。 TabContent是使用Datatemplate完成的,里面有命令。其中一个命令需要打开一个新窗口,显示TabContent中的内容。

我想做什么?我正在放置命令以打开模型中的新窗口(因为从DataTemplate开始,您在模型上下文中)。命令被正确调用,但是,我不能从我的Model中引用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);

你建议我做什么?

3 个答案:

答案 0 :(得分: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.
}

viewmodel可以访问模型,因此您可以随时进行操作。这种方法的优点是模型不需要了解它的父级,只需要有一个VM可以注册的事件。

另一个例子是https://stackoverflow.com/a/12002511/852806

注意:我同意其他答案,逻辑和数据之后不应该相同。我的回答更多地涉及数据的更改,从而导致VM中的效果,这通常是合法的。

注意2:看起来Catel可能会提供开箱即用的此类功能 - 请参阅propertychangedpropertychangedadvanced

答案 1 :(得分:0)

您的命令ShowAnotherWindow必须保留在viewmodel中。

UserControl添加RelativeSource,如下所示:

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

并将yourRootTagHere替换为您拥有的内容(WindowUserControl)。

然后,您将能够从当前视图模型中创建另一个视图模型(CompletePlotViewModel)。

答案 2 :(得分: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>

正如您所看到的,现在绑定到 viewmodel 上的 ShowAnotherWindow 。它将模型作为命令参数传递,因此您可以将其用作命令中的参数。