我正在使用框架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);
你建议我做什么?
答案 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可能会提供开箱即用的此类功能 - 请参阅propertychanged和propertychangedadvanced。
答案 1 :(得分:0)
您的命令ShowAnotherWindow
必须保留在viewmodel中。
在UserControl
添加RelativeSource
,如下所示:
<Button Command="{Binding ShowAnotherWindow},RelativeSource={RelativeSource AncestorType={x:Type yourRootTagHere},Mode=FindAncestor}">
并将yourRootTagHere
替换为您拥有的内容(Window
或UserControl
)。
然后,您将能够从当前视图模型中创建另一个视图模型(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 。它将模型作为命令参数传递,因此您可以将其用作命令中的参数。