我有一个标签部分,我正在尝试连接关闭和动态打开新标签的命令。问题是我无法理解如何从我的tabItem模板(有一个按钮)中绑定命令。这是代码:
(包含标签部分的UserControl,简化..):
<UserControl.DataContext>
<vm:InicioViewModel />
</UserControl.DataContext>
<UserControl.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="../Visual Resources/TabResource.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</UserControl.Resources>
<ContentPresenter HorizontalAlignment="Stretch" Grid.Column="1">
<ContentPresenter.Content>
<TabControl Name="tc">
<TabControl.DataContext>
<vm:WorkSpaceViewModel/>
</TabControl.DataContext>
<TabControl ItemsSource="{Binding Items}"/>
</TabControl>
</ContentPresenter.Content>
</ContentPresenter>
</Grid>
(这是tabItem的资源字典):
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type TabItem}">
<Border x:Name="TaBorder" Width="auto" Height="auto"
BorderBrush="LightGray"
BorderThickness="0.5,0.5,0.5,0"
CornerRadius="3,3,0,0"
Background="WhiteSmoke">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<TextBlock Margin="2" Grid.Column="0" Text="{TemplateBinding Header}" />
<Button x:Name="CloseButton" Grid.Column="1" Width="11" Height="11"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Background="Transparent"
DataContext="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type TabControl}}, Path=DataContext}"
Command="{Binding CloseWorkSpaceCommand}"
(Donkt know what yo put in command to reference my viewmodel Icommand)
BorderThickness="0"
>
<!-- ETC -->
(这里是我的viewModel):
class InicioViewModel : ViewModelBase
{
private WorkSpaceViewModel _workSpaceVm;
public InicioViewModel()
{
}
public WorkSpaceViewModel WorkSpaceVm
{
get { return _workSpaceVm; }
set { _workSpaceVm = value; }
}
}
(WorkSpaceViewModel ..):
public class WorkSpaceViewModel
{
private ObservableCollection<IWorkSpaceItemVm> _items;
private RelayCommand _closeWorkSpaceCommand;
public WorkSpaceViewModel()
{
_items = new ObservableCollection<IWorkSpaceItemVm>();
}
public ObservableCollection<IWorkSpaceItemVm> Items
{
get { return _items; }
set { _items = value; }
}
public ICommand CloseWorkSpaceCommand
{
get
{
return _closeWorkSpaceCommand ?? (_closeWorkSpaceCommand = new RelayCommand(
param => CloseWorkSpace_Execute(param),
param => CloseWorkSpace_CanExecute(param)
));
}
}
private void CloseWorkSpace_Execute(object parm)
{
MessageBox.Show("asdasdasd");
}
private bool CloseWorkSpace_CanExecute(object parm)
{
return true;
}
}
正如您所知,我只在CloseWorkSpace_Execute中显示一个MessageBox用于测试目的。
1)如何从我的tabItem样式模板中引用我的viewmodel中的Icommand,或者,如果有更好的方法,欢迎使用相同的结果。
2)为什么当我运行应用程序时会创建一个空选项卡,我的可观察收集列表为空
编辑: RelayCommand在程序的另一部分工作正常,这不是问题,tabItem通过触发器workin和所有来呈现OK,我仍然无法理解如何将我的viewmodel中的命令与我制作的Templated tabItem绑定。
编辑2: 该命令现在正在运行,显然命令在资源字典中未被识别,并被标记为:&#34;无法解析属性&#39; CloseWorkSpaceCommand&#39;在类型为object&#34;的DataContext中,但将按钮的DataContext设置为: DataContext =&#34; {Binding RelativeSource = {RelativeSource FindAncestor,AncestorType = {x:Type TabControl}},Path = DataContext}&#34; 在运行应用程序时完成工作(visual studio仍在为DataContext类型道歉,不知道这意味着什么)。 默认情况下仍然会创建一个选项卡,为什么? 有没有办法用DataContext类型来纠正代码味道?
答案 0 :(得分:1)
您似乎想在每个标签上添加一个关闭按钮,就像我们在浏览器中看到的一样。这样做似乎相当复杂。但是,让我试着为你分解它。
首先让我们先说明妨碍我们这样做的障碍:
- TabItem没有可以绑定CloseWorkSpaceCommand的命令属性。
- 标签项没有关闭按钮。这就是你创建模板的原因。但是仍然无法对命令属性进行模板绑定,因为TabItem没有这样的命令属性。
- 您如何将按钮的命令连接到viewmodel的CloseWorkSpaceCommand属性?
醇>
现在让我们逐个解决每个问题。
要解决此问题,我们需要为具有命令属性的TabItem创建自定义控件。
public class ClosableTabItem : TabItem
{
public static readonly DependencyProperty CloseCommandProperty = DependencyProperty.Register("CloseCommand", typeof(ICommand), typeof(ClosableTabItem), new PropertyMetadata(null));
public ICommand CloseCommand
{
get { return (ICommand)GetValue(CloseCommandProperty); }
set { SetValue(CloseCommandProperty, value); }
}
}
由于我们有自定义标签项,因此我们还需要一个自定义TabControl,因为我们需要覆盖GetContainerForItemOverride()
方法。
public class ClosableTabControl : TabControl
{
protected override DependencyObject GetContainerForItemOverride()
{
return new ClosableTabItem();
}
}
这解决了问题#1。
与您所做的一样,我们需要一个ControlTemplate,这样我们就可以在每个标签上放置一个关闭按钮。
<ControlTemplate TargetType="{x:Type local:ClosableTabItem}">
<Border x:Name="TaBorder" Width="auto" Height="auto"
Background="LightGray" CornerRadius="4,4,0,0" Margin="0,2,3,0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<TextBlock Margin="2" Grid.Column="0" Text="{TemplateBinding Header}" />
<Button x:Name="CloseButton" Grid.Column="1" Width="11" Height="11"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Command="{TemplateBinding CloseCommand}"
BorderThickness="0"
Content="X" Background="Red"
FontSize="8">
</Button>
</Grid>
</Border>
</ControlTemplate>
要将viewmodel.CloseWorkSpaceCommand绑定到Tab项,我们在ItemContainerStyle的setter中执行此操作。
<local:ClosableTabControl.ItemContainerStyle>
<Style TargetType="local:ClosableTabItem" BasedOn="{StaticResource {x:Type TabItem}}">
<Setter Property="CloseCommand" Value="{Binding DataContext.CloseWorkSpaceCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" /> ...
您会注意到我使用相对源来访问Window的DataContext。
现在将ClosableTabItem的CloseCommand属性绑定到模板内Button的Command属性,现在我们在控件模板的按钮内进行模板绑定。
您还可以在答案#2代码示例中看到这一点。
Command="{TemplateBinding CloseCommand}"
以下是完整的xaml代码:
<Window x:Class="WpfApplication1.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="clr-namespace:WpfApplication1"
mc:Ignorable="d"
Title="MainWindow" Height="350" Width="525">
<Window.DataContext>
<local:MainViewModel />
</Window.DataContext>
<Grid>
<local:ClosableTabControl ItemsSource="{Binding Items}">
<local:ClosableTabControl.ItemContainerStyle>
<Style TargetType="local:ClosableTabItem" BasedOn="{StaticResource {x:Type TabItem}}">
<Setter Property="CloseCommand" Value="{Binding DataContext.CloseWorkSpaceCommand, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}}" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="{x:Type local:ClosableTabItem}">
<Border x:Name="TaBorder" Width="auto" Height="auto"
Background="LightGray" CornerRadius="4,4,0,0" Margin="0,2,3,0">
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="20" />
</Grid.ColumnDefinitions>
<TextBlock Margin="2" Grid.Column="0" Text="{TemplateBinding Header}" />
<Button x:Name="CloseButton" Grid.Column="1" Width="11" Height="11"
VerticalAlignment="Center"
HorizontalAlignment="Center"
Command="{TemplateBinding CloseCommand}"
BorderThickness="0"
Content="X" Background="Red"
FontSize="8">
</Button>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</local:ClosableTabControl.ItemContainerStyle>
<TabControl.Items>
</TabControl.Items>
</local:ClosableTabControl>
</Grid>
</Window>