Enlace de WPF a Listbox selectedItem
binding (5)
Dentro de la DataTemplate
está trabajando en el contexto de una Rule
, por eso no puede enlazar con SelectedRule.Name
: no hay tal propiedad en una Rule
. Para enlazar con el contexto de datos original (que es su ViewModel) puede escribir:
<TextBlock Text="{Binding ElementName=lbRules, Path=DataContext.SelectedRule.Name}" />
ACTUALIZACIÓN: con respecto al enlace de propiedad SelectedItem, parece perfectamente válido, intenté lo mismo en mi máquina y funciona bien. Aquí está mi aplicación de prueba completa:
XAML:
<Window x:Class="TestWpfApplication.ListBoxSelectedItem"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
Title="ListBoxSelectedItem" Height="300" Width="300"
xmlns:app="clr-namespace:TestWpfApplication">
<Window.DataContext>
<app:ListBoxSelectedItemViewModel/>
</Window.DataContext>
<ListBox ItemsSource="{Binding Path=Rules}" SelectedItem="{Binding Path=SelectedRule, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name:" />
<TextBox Text="{Binding Name}"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Window>
Código detrás:
namespace TestWpfApplication
{
/// <summary>
/// Interaction logic for ListBoxSelectedItem.xaml
/// </summary>
public partial class ListBoxSelectedItem : Window
{
public ListBoxSelectedItem()
{
InitializeComponent();
}
}
public class Rule
{
public string Name { get; set; }
}
public class ListBoxSelectedItemViewModel
{
public ListBoxSelectedItemViewModel()
{
Rules = new ObservableCollection<Rule>()
{
new Rule() { Name = "Rule 1"},
new Rule() { Name = "Rule 2"},
new Rule() { Name = "Rule 3"},
};
}
public ObservableCollection<Rule> Rules { get; private set; }
private Rule selectedRule;
public Rule SelectedRule
{
get { return selectedRule; }
set
{
selectedRule = value;
}
}
}
}
¿Puede alguien ayudar con lo siguiente? Estar jugando con esto, pero no puedo, por mi vida, hacer que funcione.
Tengo un modelo de vista que contiene las siguientes propiedades;
public ObservableCollection<Rule> Rules { get; set; }
public Rule SelectedRule { get; set; }
En mi XAML tengo;
<ListBox x:Name="lbRules" ItemsSource="{Binding Path=Rules}"
SelectedItem="{Binding Path=SelectedRule, Mode=TwoWay}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<TextBlock Text="Name:" />
<TextBox x:Name="ruleName">
<TextBox.Text>
<Binding Path="Name" UpdateSourceTrigger="PropertyChanged" />
</TextBox.Text>
</TextBox>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
Ahora, el ItemsSource funciona bien y obtengo una lista de objetos de Reglas con sus nombres mostrados en lbRules.
El problema que tengo es vincular la propiedad SelectedRule con SelectedItem de lbRules. Intenté enlazar la propiedad de texto de un bloque de texto a SelectedRule pero siempre es nula.
<TextBlock Text="{Binding Path=SelectedRule.Name}" />
El error que veo en la ventana de resultados es: Error de ruta de BindingExpression: no se encontró la propiedad ''SelectedRule''.
¿Puede alguien ayudarme con este enlace? No puedo ver por qué no debería encontrar la propiedad SelectedRule.
Luego intenté cambiar la propiedad de texto del bloque de texto como a continuación, que funciona. El problema es que quiero usar el SelectedRule en mi ViewModel.
<TextBlock Text="{Binding ElementName=lbRules, Path=SelectedItem.Name}" />
Muchas gracias por su ayuda.
En primer lugar, debe implementar la interfaz INotifyPropertyChanged
en su modelo de vista y elevar el evento PropertyChanged
en el setter de la propiedad Rule
. De lo contrario, ningún control que se enlace a la propiedad SelectedRule
se "sabrá" cuando se haya cambiado.
Entonces, tu XAML
<TextBlock Text="{Binding Path=SelectedRule.Name}" />
es perfectamente válido si este TextBlock
está fuera del ItemTemplate
del ListBox
y tiene el mismo DataContext
que el ListBox
.
Para mí, normalmente uso DataContext
para enlazar propiedades de dos profundidades como esta pregunta.
<TextBlock DataContext="{Binding SelectedRule}" Text="{Binding Name}" />
O, prefiero usar ElementName
porque solo logra enlaces con controles de vista.
<TextBlock DataContext="{Binding ElementName=lbRules, Path=SelectedItem}" Text="{Binding Name}" />
Yocoder tiene razón,
Dentro de DataTemplate
, su DataContext
se establece en la Rule
está manejando actualmente.
Para acceder al DataContext
los padres, también puede considerar el uso de un RelativeSource
en su enlace:
<TextBlock Text="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ____Your Parent control here___ }}, Path=DataContext.SelectedRule.Name}" />
Más información sobre RelativeSource
se puede encontrar aquí:
http://msdn.microsoft.com/en-us/library/system.windows.data.relativesource.aspx
ya que configura su fuente de elementos para su colección, su cuadro de texto está vinculado a cada elemento individual de esa colección. la propiedad del elemento seleccionado es útil en este escenario si intentaba hacer un formulario de detalles maestros, con 2 cuadros de lista. vincularía la fuente de elementos del segundo cuadro de lista a la colección secundaria de reglas. en otras palabras, el elemento seleccionado alerta sobre los controles externos de que su fuente ha cambiado, los controles internos (aquellos que están dentro de su plantilla de datos ya son conscientes del cambio).
y para responder a su pregunta, sí, en la mayoría de las circunstancias, establecer la fuente de elementos es lo mismo que configurar el contexto de datos del control.