更改 DataContext 以进行 ControlTemplate 处理
Change DataContext for ControlTemplate handling
我有一个小应用程序,其中有一个模型树,我希望根据双击的项目,不同的视图应该出现在 ContentControl 中。
enter image description here
我创建了一个命令来更改 ContentControl 视图,但问题是 TreeView 的 DataContext 是“TreeItemModel”,其中我拥有显示树和子项的所有数据,但命令和视图处理在“MainViewModel”中编程,所以我不能 select 命令。
enter image description here
任何人都知道我该如何处理这个问题并能够继续使用我的 TreeItemModel 但 MainViewModel 来处理这个命令?
XAML代码:
<Grid Grid.Row="3" Background="#FFF0F0F0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30*" MaxWidth="350"/>
<ColumnDefinition Width="70*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Margin="5">
<TreeView x:Name ="TreeModel" ItemsSource="{Binding MainTree}" PreviewMouseDoubleClick="TreeView_PreviewMouseDoubleClick">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type model:TreeItemModel}" ItemsSource="{Binding Path=Elements}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.25*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding Path=Icon}" MaxHeight="30" MaxWidth="30" HorizontalAlignment="Left"/>
<TextBlock Grid.Column="1" Text="{Binding Path=Name}" Margin="5,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Center"/>
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="commandBehaviors:MouseDoubleClick.Command" Value="{Binding DoubleClickCmd}"/>
<Setter Property="commandBehaviors:MouseDoubleClick.CommandParameter" Value="{Binding}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
</StackPanel>
<ContentControl Grid.Column="1"
Margin="10"
Content="{Binding CurrentView}"/>
</Grid>
MainViewModel 代码:
class MainViewModel
{
// Command when double clicking in tree item
public RelayCommand DoubleClickCmd { get; set; }
string ObjPath;
public List<TreeItemModel> MainTree { get; set; }
public TreeItemModel MainObject { get; set; }
public VariablesViewModel VariableVM { get; set; }
private object _currentView;
public object CurrentView
{
get { return _currentView; }
set
{
_currentView = value;
OnPropertyChanged();
}
}
public MainViewModel()
{
VariableVM = new VariablesViewModel();
// Command that i want ot execute
DoubleClickCmd = new RelayCommand(o =>
{
CurrentView = VariableVM;
});
}
}
最简单的方法是使用 RelativeSource 绑定:
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="commandBehaviors:MouseDoubleClick.Command" Value="{Binding DataContext.DoubleClickCmd, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
<Setter Property="commandBehaviors:MouseDoubleClick.CommandParameter" Value="{Binding .}"/>
</Style>
</TreeView.ItemContainerStyle>
另一种解决方法是使用 Proxy class,它会将您的 DataContext 保存在变量中,例如 Proxy,请参阅:https://code.4noobz.net/wpf-mvvm-proxy-binding/
我有一个小应用程序,其中有一个模型树,我希望根据双击的项目,不同的视图应该出现在 ContentControl 中。 enter image description here
我创建了一个命令来更改 ContentControl 视图,但问题是 TreeView 的 DataContext 是“TreeItemModel”,其中我拥有显示树和子项的所有数据,但命令和视图处理在“MainViewModel”中编程,所以我不能 select 命令。 enter image description here
任何人都知道我该如何处理这个问题并能够继续使用我的 TreeItemModel 但 MainViewModel 来处理这个命令?
XAML代码:
<Grid Grid.Row="3" Background="#FFF0F0F0">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="30*" MaxWidth="350"/>
<ColumnDefinition Width="70*"/>
</Grid.ColumnDefinitions>
<StackPanel Grid.Column="0" Margin="5">
<TreeView x:Name ="TreeModel" ItemsSource="{Binding MainTree}" PreviewMouseDoubleClick="TreeView_PreviewMouseDoubleClick">
<TreeView.ItemTemplate>
<HierarchicalDataTemplate DataType="{x:Type model:TreeItemModel}" ItemsSource="{Binding Path=Elements}">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="0.25*"/>
<ColumnDefinition Width="*"/>
</Grid.ColumnDefinitions>
<Image Grid.Column="0" Source="{Binding Path=Icon}" MaxHeight="30" MaxWidth="30" HorizontalAlignment="Left"/>
<TextBlock Grid.Column="1" Text="{Binding Path=Name}" Margin="5,0,0,0" HorizontalAlignment="Right" VerticalAlignment="Center"/>
</Grid>
</HierarchicalDataTemplate>
</TreeView.ItemTemplate>
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="commandBehaviors:MouseDoubleClick.Command" Value="{Binding DoubleClickCmd}"/>
<Setter Property="commandBehaviors:MouseDoubleClick.CommandParameter" Value="{Binding}"/>
</Style>
</TreeView.ItemContainerStyle>
</TreeView>
</StackPanel>
<ContentControl Grid.Column="1"
Margin="10"
Content="{Binding CurrentView}"/>
</Grid>
MainViewModel 代码:
class MainViewModel
{
// Command when double clicking in tree item
public RelayCommand DoubleClickCmd { get; set; }
string ObjPath;
public List<TreeItemModel> MainTree { get; set; }
public TreeItemModel MainObject { get; set; }
public VariablesViewModel VariableVM { get; set; }
private object _currentView;
public object CurrentView
{
get { return _currentView; }
set
{
_currentView = value;
OnPropertyChanged();
}
}
public MainViewModel()
{
VariableVM = new VariablesViewModel();
// Command that i want ot execute
DoubleClickCmd = new RelayCommand(o =>
{
CurrentView = VariableVM;
});
}
}
最简单的方法是使用 RelativeSource 绑定:
<TreeView.ItemContainerStyle>
<Style TargetType="{x:Type TreeViewItem}">
<Setter Property="commandBehaviors:MouseDoubleClick.Command" Value="{Binding DataContext.DoubleClickCmd, RelativeSource={RelativeSource Mode=FindAncestor, AncestorType={x:Type Window}}}"/>
<Setter Property="commandBehaviors:MouseDoubleClick.CommandParameter" Value="{Binding .}"/>
</Style>
</TreeView.ItemContainerStyle>
另一种解决方法是使用 Proxy class,它会将您的 DataContext 保存在变量中,例如 Proxy,请参阅:https://code.4noobz.net/wpf-mvvm-proxy-binding/