Estoy tratando de agregar un botón a un ListView personalizado (MyListView) que desencadena un comando (MyCustomCommand) definido en MyListView. He agregado el botón (y un texto de título) aplicando una plantilla de control. El problema es que no he encontrado una manera de activar MyCustomCommand al hacer clic en el botón. Lo que finalmente quiero lograr es abrir un Popup o ContextMenu donde pueda seleccionar qué columnas deberían estar visibles en ListView.WPF: Enlace al comando de ControlTemplate
Aquí es mi fuente de plantilla:
<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>
Aquí es la definición de 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; }
}
Y aquí es el XAML que se crea una instancia sencilla de 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>
Observe HeaderTitle que está vinculado a DependencyProperty en MyListView. Esto funciona como se esperaba ¿Por qué no funciona de la misma manera con los comandos? ¿Alguna pista de cómo hacer que esto funcione?
Gracias mucho. Eso resolvió mi caso :) Ahora puedo abrir una ventana emergente cuando se ejecuta el comando. –
Me he encontrado con un nuevo problema ... El botón para activar el comando solo está disponible (habilitado) en la primera instancia de MyListView en una ventana. Tiene algo que ver con la palabra clave estática en: Command = {x: Static local: MyListView.MyCustomCommand} –
Los botones con comandos se deshabilitan cuando el comando CanExecute es falso o el comando no tiene asociado el controlador Execute. Asegúrese de que no ocurra nada extraño con CanExecute y que CommandBinding se esté configurando en cada instancia de ListView y no en un contexto estático que solo afectará al primero. –