template data c# wpf xaml data-binding mvvm

c# - mvvm datatemplate



Enlazar el botón en el comando DataTemplate al comando en el ViewModel del formulario (1)

Sus:

{Binding DataContext.FireCommand, RelativeSource={RelativeSource AncestorType=ListBox}}

No es necesario ir a la raíz a menos que realmente cambie el DataContext en el camino, pero como el ListBox parece vincularse a una propiedad en la máquina virtual principal, esto debería ser suficiente.

Lo único que recomiendo leer es la Descripción general de enlace de datos y la documentación de la clase de Binding (incluidas sus propiedades).

También aquí hay una breve explicación sobre cómo se construyen las vinculaciones: una vinculación consiste en una fuente y una Path relativa a esa fuente , por defecto la fuente es el DataContext actual. Las fuentes que pueden establecerse explícitamente son: Source , ElementName y RelativeSource . Establecer cualquiera de ellos anulará el DataContext como fuente .

Entonces, si usa una fuente como RelativeSource y desea acceder a algo en el DataContext en ese nivel, DataContext debe aparecer en la Path .

Mi problema es similar al descrito en esta pregunta:
WPF MVVM Button Control Binding en DataTemplate

Aquí está mi XAML:

<Window x:Class="MissileSharp.Launcher.MainWindow" xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" Title="MissileSharp Launcher" Height="350" Width="525"> <Grid> <!-- when I put the button here (outside the list), the binding works --> <!--<Button Content="test" Command="{Binding Path=FireCommand}" />--> <ListBox ItemsSource="{Binding CommandSets}"> <ListBox.ItemTemplate> <DataTemplate> <!-- I need the button here (inside the list), and here the binding does NOT work --> <Button Content="{Binding}" Command="{Binding Path=FireCommand}" /> </DataTemplate> </ListBox.ItemTemplate> </ListBox> </Grid> </Window>

Es solo un ListBox , ligado a un ObservableCollection<string> llamado CommandSets (que está en el ViewModel).
Este enlace funciona (muestra un botón para cada elemento de la colección).

Ahora quiero vincular el botón a un comando ( FireCommand ), que también está en ViewModel.
Aquí está la parte relevante de ViewModel:

public class MainWindowViewModel : INotifyPropertyChanged { public ICommand FireCommand { get; set; } public ObservableCollection<string> CommandSets { get; set; } public MainWindowViewModel() { this.FireCommand = new RelayCommand(new Action<object>(this.FireMissile)); } private void FireMissile(Object obj) { System.Windows.MessageBox.Show("fire"); } }

El enlace de este botón NO funciona.
Según lo que he entendido por la pregunta que he vinculado anteriormente, el enlace no funciona porque:
(Corrígeme si estoy equivocado)

  • El botón está dentro del ListBox , por lo que solo "conoce" el enlace del ListBox (el ObservableCollection , en este caso), pero no el enlace de la ventana principal
  • Estoy tratando de enlazar a un comando en el ViewModel principal de la ventana principal (que el botón no "sabe")

El comando en sí es definitivamente correcto, porque cuando coloco el botón fuera del ListBox (vea el XAML arriba para un ejemplo), el enlace funciona y el comando se ejecuta.

Aparentemente, solo "necesito" decirle al botón que se vincule con el ViewModel principal del formulario.
Pero no puedo descifrar la sintaxis correcta de XAML.

Probé varios enfoques que encontré después de buscar en Google, pero ninguno de ellos funcionó para mí:

<Button Content="{Binding}" Command="{Binding RelativeSource={RelativeSource Window}, Path=DataContext.FireCommand}" /> <Button Content="{Binding}" Command="{Binding Path=FireCommand, Source={StaticResource MainWindow}}" /> <Button Content="{Binding}" Command="{Binding Path=FireCommand, RelativeSource={RelativeSource AncestorType={x:Type Window}}}" />

¿Podría alguien por favor?

  1. dame el XAML adecuado para vincular el botón dentro de ListBox a un comando en MainViewModel del MainViewModel ?
  2. ¿Dirígeme a un enlace donde se explican las cosas avanzadas de enlace de una manera que un principiante de WPF / MVVM puede entender?
    Siento que estoy copiando y pegando hechizos XAML arcanos, y hasta ahora no tengo ni idea (y no puedo encontrar ninguna buena documentación) de cómo resolvería por mí mismo en qué casos necesitaría RelativeSource o StaticResource o lo que sea, en lugar de un enlace "normal".