2016-04-27 113 views
0

您好,我尝试创建一个自定义的TabItem与删除按钮,我想绑定我的viewmodel命令到我的自定义依赖属性'DeleteCommandProperty'。有人能告诉我我做错了什么吗?带删除按钮绑定的WPF自定义TabItem问题

我的自定义的TabControl:

/// <summary> 
    /// TabControl withCustom TabItem 
    /// </summary> 
    public class MyTabControl:TabControl 
    { 
     /// <summary> 
     /// TabItem override 
     /// </summary> 
     /// <returns></returns> 
     protected override DependencyObject GetContainerForItemOverride() 
     { 
      return new MyTabItem(); 
     } 
    } 

我的自定义的TabItem类:

/// <summary> 
    /// Custom TabItem 
    /// </summary> 
    public class MyTabItem:TabItem 
    { 
     /// <summary> 
     /// Delete Command 
     /// </summary> 
     public static DependencyProperty DeleteCommandProperty = DependencyProperty.Register(
      "DeleteCommand",typeof(ICommand),typeof(MyTabItem)); 

     /// <summary> 
     /// Delete 
     /// </summary> 
     public ICommand DeleteCommand 
     { 
      get { return (ICommand)GetValue(DeleteCommandProperty); } 
      set { SetValue(DeleteCommandProperty, value); } 
     } 
    } 

当我直接绑定的DeleteCommand这样我在我的视图模型,执行指令

<customControls:MyTabControl> 
      <customControls:MyTabItem Header="Test" DeleteCommand="{Binding DeleteStudiengangCommand}" Template="{DynamicResource MyTabItemControlTemplate}"/> 
     </customControls:MyTabControl> 

BU当试图像这样通过样式绑定deleteCommand但它不起作用:

<Style TargetType="customControls:MyTabItem"> 
         <Setter Property="Template" Value="{DynamicResource MyTabItemControlTemplate}"/> 
         <Setter Property="DeleteCommand" Value="{Binding MyDeleteCommand}"/> 
        </Style> 



<customControls:MyTabControl ItemsSource="{Binding MyList}" SelectedItem="{Binding SelectedItem}" SelectedIndex="0"> 
        <customControls:MyTabControl.ContentTemplate> 
         <DataTemplate> 
          <ItemsControl ItemsSource="{Binding Value}" > 
           <ItemsControl.ItemsPanel> 
            <ItemsPanelTemplate> 
             <WrapPanel/> 
            </ItemsPanelTemplate> 
           </ItemsControl.ItemsPanel> 
          </ItemsControl> 
         </DataTemplate> 
        </customControls:MyTabControl.ContentTemplate> 
       </customControls:MyTabControl> 
+0

考虑将其降低到[MVCE](http://stackoverflow.com/help/mcve)。例如,不要尝试在你的样式中绑定'DeleteCommand',除非它是显示你的问题的必要条件......相反,在你的构造函数中分配一个静态命令 – grek40

+0

我看到你以某种方式编辑了你的问题,但它很远从最小**(你用很多与你的问题无关的模板),远不是**可验证**(我用你的基于样式的命令setter创建了一个小例子,它工作得很好),远从**完整**(其中是'customControls:MyTabControl'的代码?另外,请不要强迫我使用Blend),并且你没有真正解释观察到的行为与预期的行为形成对比,所以也没有**例子**。 – grek40

+0

我添加了我的TabControl类,并试图解释什么没有工作希望有人可以帮助 – Johannes

回答

2

TL; DR

我怀疑你的DataContext包含MyList您的当前项目(不管它是什么),所以你计划的风格二传手无法访问MyDeleteCommand属性。查看visual studio调试器日志,了解是否在那里记录绑定异常。


从工作代码发展到直到发现可能的问题解释的例子。

看来你对降低你的榜样一定的困难,所以我唯一能会根据您提供的信息提供与StyleTemplateBinding办法一个小的工作例如,你可以作为一个基地使用,以确定你真正的问题。 编辑:在最后的解释可能实际上是你的问题的答案。

请注意,您可能必须更改名称空间以与您的项目设置相匹配。

MainWindow.xaml

<Window x:Class="WpfApplication2.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:local="clr-namespace:WpfApplication2" 
     Title="MainWindow" Height="350" Width="525" 
     Loaded="Window_Loaded"> 

    <Window.Resources> 
     <!-- Header template --> 
     <ControlTemplate x:Key="MyTabItemControlTemplate" TargetType="{x:Type local:MyTabItem}"> 
      <!-- Some text and the command button with template binding --> 
      <StackPanel Orientation="Horizontal" Background="Aquamarine" Margin="3"> 
       <ContentPresenter Content="{TemplateBinding Header}" VerticalAlignment="Center" Margin="2"/> 
       <Button Content="Delete" Command="{TemplateBinding DeleteCommand}" Margin="2"/> 
      </StackPanel> 
     </ControlTemplate> 

     <!-- Setting the control template and assigning the command implementation --> 
     <Style TargetType="{x:Type local:MyTabItem}"> 
      <Setter Property="Template" Value="{DynamicResource MyTabItemControlTemplate}"/> 
      <Setter Property="DeleteCommand" Value="{Binding MyDeleteCommand}"/> 
      <Setter Property="Header" Value="Default Header Text"/> 
     </Style> 
    </Window.Resources> 

    <Grid> 
     <local:MyTabControl ItemsSource="{Binding MyTabItemList}"/> 
    </Grid> 
</Window> 

MainWindow.xaml.cs的例子

​​

摘要: 你看到三个不同的标签,每个标签具有其独特的构造和外观:

  1. 该选项卡项是从GetContainerForItemOverride方法创建的,Header属性的样式设置器指定了在标题中出现的文本。 MyDeleteCommand绑定不起作用!
  2. 该标签项目被提供为带有标头和内容值的MyTabItemHeader属性的样式设置器不适用,因为该属性是明确设置的。 DeleteCommand属性的样式设置器绑定到MyContextMyDeleteCommand属性。
  3. 该标签项目被提供为TabItem,并且因为没有覆盖MyTabControl.IsItemItsOwnContainerOverride,所以这被接受为MyTabControl的控制项目。整个MyTabItem模板不适用。

在Visual Studio中的调试输出给出了关于第一个选项卡项目潜在的问题提示:

System.Windows.Data Error: 40 : BindingExpression path error: 'MyDeleteCommand' property not found on 'object' ''TextBlock' (Name='')'. BindingExpression:Path=MyDeleteCommand; DataItem='TextBlock' (Name=''); target element is 'MyTabItem' (Name=''); target property is 'DeleteCommand' (type 'ICommand')

的原因是,当前选项卡项目内容在这种情况下成为新的本地DataContext不像第二个选项卡项目,项目本身被接受为容器。

一个解决办法是,以确保该命令绑定propper上下文用法:

应该你给一个名字x:Name="_this",那么你就可以访问父DataContext一些合适的父元素。

<Setter Property="DeleteCommand" Value="{Binding DataContext.MyDeleteCommand,ElementName=_this}"/> 
+0

谢谢指定DataContext像你说的那样解决了问题。 – Johannes