TL; DR
Ich vermute, Ihre DataContext
von MyList
Ihr aktuelles Element enthält (was auch immer es ist), so dass der Stil Setter kann nicht auf die MyDeleteCommand
Eigenschaft als Sie geplant. Sehen Sie sich das Visual Studio Debugger-Protokoll an, ob dort eine verbindliche Ausnahme protokolliert wird.
Beispiel, die von einem funktionierenden Code entwickelt, bis es ein mögliches Problem Erklärung offenbaren passiert ist.
Es scheint einige Schwierigkeiten haben, Ihr Beispiel bei der Reduzierung, so das einzige, was ich kann Ihnen auf die Informationen, die Sie bieten auf Basis ist ein kleines Arbeitsbeispiel mit dem Style
und TemplateBinding
Ansatz, die Sie als Basis verwenden können, zu identifizieren dein echtes Problem. Bearbeiten: Die Erklärung am Ende könnte tatsächlich die Antwort auf Ihre Frage sein.
Hinweis: Möglicherweise müssen Sie die Namespaces ändern, damit sie mit Ihrer Projektkonfiguration übereinstimmen.
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
/// <summary>
/// TabControl withCustom TabItem
/// </summary>
public class MyTabControl : TabControl
{
/// <summary>
/// TabItem override
/// </summary>
protected override DependencyObject GetContainerForItemOverride()
{
return new MyTabItem();
}
}
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); }
}
}
public class MyCommand : ICommand
{
public void Execute(object parameter)
{
MessageBox.Show("Hello WPF", "Message");
}
public bool CanExecute(object parameter)
{
return true;
}
public event EventHandler CanExecuteChanged { add { } remove { } }
}
public class MyContext
{
public ICommand MyDeleteCommand { get; set; }
public List<object> MyTabItemList { get; set; }
}
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void Window_Loaded(object sender, RoutedEventArgs e)
{
var list = new List<object>();
list.Add(new TextBlock() { Text = "Test 1" });
list.Add(new MyTabItem() { Content = "Test Content 2", Header = "Test Header 2" });
list.Add(new TabItem() { Content = "Test Content 3", Header = "Test Header 3" });
this.DataContext = new MyContext()
{
MyTabItemList = list,
MyDeleteCommand = new MyCommand()
};
}
}
Zusammenfassung des Beispiels: Sie sehen drei verschiedene Registerkarten, die jeweils mit ihrem einzigartigen Aufbau und Aussehen:
- Der Registerkarteneintrag wird aus der
GetContainerForItemOverride
-Methode erstellt. Der Stilausrichter für die Eigenschaft Header
gibt den Text an, der in der Kopfzeile angezeigt wird. Die MyDeleteCommand
Bindung funktioniert nicht!
- Der Tab-Eintrag wird als
MyTabItem
mit Header und Inhaltswert bereitgestellt. Der Style-Setter für die Header
-Eigenschaft gilt nicht, da die Eigenschaft explizit festgelegt ist. Der Stilsetzer für die DeleteCommand
-Eigenschaft bindet die MyDeleteCommand
-Eigenschaft von .
- Das Registerelement wird als
TabItem
bereitgestellt, und da es keine Außerkraftsetzung von MyTabControl.IsItemItsOwnContainerOverride
gibt, wird dies als Steuerelement von MyTabControl
akzeptiert. Die gesamte Vorlage MyTabItem
gilt nicht.
Die Ausgabe Debuggen in Visual Studio gibt einen Hinweis auf das zugrunde liegende Problem für das erste Element tab:
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')
Der Grund dafür ist, dass der aktuelle Registerkarte Elementinhalt die neuen lokalen DataContext
in diesem Szenario wird Im Gegensatz zum zweiten Tab-Element, bei dem das Objekt selbst als Container akzeptiert wird.
könnte eine Lösung sein Nutzung des Propper Kontext binden den Befehl, um sicherzustellen:
Vermeintliche Sie einige geeignete Eltern-Element einen Namen geben x:Name="_this"
, dann können Sie DataContext
die Eltern zugreifen.
<Setter Property="DeleteCommand" Value="{Binding DataContext.MyDeleteCommand,ElementName=_this}"/>
Sie können dies auf [MVCE] reduzieren (http://stackoverflow.com/help/mcve). Versuchen Sie beispielsweise nicht, den 'DeleteCommand' in Ihrem Stil zu binden, es sei denn, es ist wichtig, Ihr Problem zu zeigen ... Weisen Sie stattdessen einen statischen Befehl in Ihrem Konstruktor – grek40
Ich sehe Sie Ihre Frage irgendwie bearbeitet, aber es ist sehr weit von ** minimal ** (Sie verwenden weit zu viele Vorlagen, die nicht mit Ihrem Problem zusammenhängen), weit davon entfernt, ** verifizierbar ** zu sein (Ich baute ein kleines Beispiel mit Ihrem style-basierten Befehlssatz und es funktionierte gut), weit aus ** complete ** (wo ist der Code für 'customControls: MyTabControl'? auch, bitte zwing mich nicht, Blend zu verwenden) und du erklärst nicht wirklich, was das beobachtete Verhalten im Gegensatz zu dem erwarteten Verhalten ist, Also ist auch kein ** Beispiel ** angegeben. – grek40
Ich habe meine TabControl-Klasse hinzugefügt und versuche zu erklären, was nicht funktioniert habe hoffe, dass jemand helfen kann – Johannes