WPF: Bind-Befehl von ControlTemplate
Ich versuche eine Schaltfläche hinzufügen, um eine benutzerdefinierte ListView (MyListView -) was löst einen Befehl (MyCustomCommand), definiert in MyListView. Ich habe den button (und ein Titel-text) durch die Anwendung einer ControlTemplate. Das problem ist, dass ich habe nicht gefunden, einen Weg, um die trigger-MyCustomCommand bei Klick auf die Schaltfläche. Was ich letztendlich erreichen will, ist das öffnen eines Popup-oder Kontextmenü wo ich auswählen kann, welche Spalten sichtbar sein sollen in der ListView.
Hier ist meine Vorlage, Quelle:
<Style TargetType="local:MyListView">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:MyListView">
<Border Name="Border" BorderThickness="1" BorderBrush="Black">
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="30" />
<RowDefinition />
</Grid.RowDefinitions>
<Grid Background="LightSteelBlue">
<Grid.ColumnDefinitions>
<ColumnDefinition />
<ColumnDefinition Width="Auto" />
</Grid.ColumnDefinitions>
<TextBlock Margin="3,3,3,3" Text="{TemplateBinding HeaderTitle}" Grid.Column="0" VerticalAlignment="Center" HorizontalAlignment="Stretch" FontSize="16" />
<Button Margin="3,3,3,3" Grid.Column="1"
VerticalAlignment="Center" HorizontalAlignment="Right" Height="20"
Command="{TemplateBinding MyCustomCommand}">A button</Button>
</Grid>
<ScrollViewer Grid.Row="1" Style="{DynamicResource {x:Static GridView.GridViewScrollViewerStyleKey}}">
<ItemsPresenter />
</ScrollViewer>
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
Hier ist die definition für MyListView:
public class MyListView : ListView
{
public static readonly DependencyProperty MyCustomCommandProperty =
DependencyProperty.Register("MyCustomCommand", typeof(ICommand), typeof(MyListView));
private static RoutedCommand myCustomCommand;
public ICommand MyCustomCommand
{
get
{
if (myCustomCommand == null)
{
myCustomCommand = new RoutedCommand("MyCustomCommand", typeof(MyListView));
var binding = new CommandBinding();
binding.Command = myCustomCommand;
binding.Executed += binding_Executed;
CommandManager.RegisterClassCommandBinding(typeof(MyListView), binding);
}
return myCustomCommand;
}
}
private static void binding_Executed(object sender, ExecutedRoutedEventArgs e)
{
MessageBox.Show("Command Handled!");
}
public static readonly DependencyProperty HeaderTitleProperty =
DependencyProperty.Register("HeaderTitle", typeof(string), typeof(MyListView));
public string HeaderTitle { get; set; }
}
Und hier ist der XAML-Code, der erstellt eine einfache Instanz von MyListView:
<local:MyListView VerticalAlignment="Top" HeaderTitle="ListView title">
<ListView.View>
<GridView>
<GridViewColumn Width="70" Header="Column 1" />
<GridViewColumn Width="70" Header="Column 2" />
<GridViewColumn Width="70" Header="Column 3" />
</GridView>
</ListView.View>
<ListViewItem>1</ListViewItem>
<ListViewItem>2</ListViewItem>
<ListViewItem>1</ListViewItem>
<ListViewItem>2</ListViewItem>
</local:MyListView>
Bemerken HeaderTitle, die gebunden ist an die DependencyProperty in MyListView. Dies funktioniert wie erwartet. Warum werden nicht die gleiche Weise arbeiten mit Befehle? Irgendwelche Hinweise, wie diese Arbeit zu machen?
Du musst angemeldet sein, um einen Kommentar abzugeben.
Sollten Sie beginnen, indem Sie die wrapper-Eigenschaft für den Befehl statische und verwenden
In der Regel wollen Sie nur eine ICommand-Eigenschaft, wenn der Befehl gesetzt wird, um einen unterschiedlichen Wert für jede Instanz (like-Button) oder wenn es etwas wie ein DelegateCommand/RelayCommand auf ein ViewModel. Sollten Sie auch entfernen Sie alle zusätzlichen code in die getter-und stattdessen initialisieren der Befehl entweder inline oder im statischen Konstruktor und schließen Sie das CommandBinding in der control-Instanz-Konstruktor.
**UPDATE
Den RoutedCommand selbst sollte als statisch deklariert. ICommand-Instanz-Eigenschaften sind gut für, wenn ein externer Verbraucher Ihre Kontrolle übergeben wird, in einen Befehl ausführen, das ist nicht das, was Sie hier wollen. Es gibt auch keine Notwendigkeit für einen DP hier und den, den Sie verwenden, ist falsch deklariert - verwendbar sein, müssen Sie die Instanz der wrapper-Eigenschaften mit GetValue/SetValue.
Ich bin nicht sicher, ob dies der richtige Weg, dies zu tun. Es ist ein bisschen schwer zu Lesen-source-code in den Kommentaren, so Schreibe ich diese Antwort als Antwort...
Hier ist der Konstruktor der MyListView - + der Befehl Bindeverfahren:
Sind die Bindungen nicht in einem statischen Kontext. Die einzigen Dinge, die sind statisch sind die DependencyProperty für den Befehl, und der Befehl selbst:
Den Befehl muss statisch sein, um in der Lage zu binden, um es aus dem XAML-Code wie dieser: