He estado leyendo mucho sobre MVVM (usando la biblioteca de Laurent Bugnion en concreto) y estoy luchando constantemente para determinar cómo hacer las cosas en MVVM que eran de otra forma fácil con código detrás.MVVM cuadro de lista de actualización de contenido Mantener el elemento seleccionado Silverlight
Aquí hay solo un ejemplo en el que sospecho que estoy haciendo las cosas de la manera difícil. Si alguien tiene tiempo para leer todo esto, quizás puedan comentar sobre la cordura de mi enfoque. :)
I tienen un cuadro de lista unido a un ViewModel como tan:
<ListBox x:Name="lstFruitBasketLeft" ItemsSource="{Binding FruitBasket}"
SelectedItem="{Binding SelectedFruit, Mode=TwoWay}" Width="150">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal" VerticalAlignment="Center"
HorizontalAlignment="Left" Margin="2">
<TextBlock Text="{Binding Name}" />
<TextBlock Text=":" />
<TextBlock Text="{Binding Quantity}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
El ItemSource es un ObservableCollection de objetos de frutas:
public class Fruit
{
public string Name { get; set; }
public int Quantity { get; set; }
public Fruit() { }
public Fruit(string name, int quantity)
{
this.Name = name;
this.Quantity = quantity;
}
}
Se define en la ViewModel como:
// Property FruitBasket
public const string FruitBasketPropertyName = "FruitBasket";
private ObservableCollection<Fruit> _fruitBasket = null;
public ObservableCollection<Fruit> FruitBasket
{
get { return _fruitBasket; }
set
{
if (_fruitBasket == value)
return;
_fruitBasket = value;
// Update bindings, no broadcast
RaisePropertyChanged(FruitBasketPropertyName);
}
}
La propiedad SelectedItem ligados es como tal:
//Property SelectedFruit
public const string SelectedFruitPropertyName = "SelectedFruit";
private Fruit _selectedFruit = null;
public Fruit SelectedFruit
{
get { return _selectedFruit; }
set
{
if (_selectedFruit == value)
return;
var oldValue = _selectedFruit;
_selectedFruit = value;
// Update bindings, no broadcast
RaisePropertyChanged(SelectedFruitPropertyName);
}
}
A continuación, la lista se rellena en la construcción del modelo de vista.
Ahora, agrego un RelayCommand a un botón en la página de presentación que ejecuta un método que incrementa la cantidad del elemento seleccionado. Tenga en cuenta que todavía no estoy usando el parámetro, pero "Bob" es un marcador de posición para algunos cambios para más adelante.
<Button x:Name="butMore" Content="More!" HorizontalAlignment="Right" Height="25" Width="75" Margin="4">
<i:Interaction.Triggers>
<i:EventTrigger EventName="Click">
<cmd:EventToCommand
Command="{Binding addMoreCommand}"
CommandParameter="Bob" />
</i:EventTrigger>
</i:Interaction.Triggers>
</Button>
Aquí está el código para el comando:
// Property addMoreCommand
public RelayCommand addMoreCommand
{
get;
private set;
}
...
//Init relays (this is in the constructor)
addMoreCommand = new RelayCommand(AddFruit, CanExecute);
...
public void AddFruit()
{
//Increment the fruit
SelectedFruit.Quantity++;
//Save the previous selected item
Fruit oldSelectedItem = SelectedFruit;
//We have to have a new list in order to get the list box to refresh
FruitBasket = new ObservableCollection<Fruit>(FruitBasket);
//Reselect
SelectedFruit = oldSelectedItem;
}
public bool CanExecute()
{
return true; //for now
}
Ahora bien, esto funciona, pero tengo un poco problemas con él:
Primero, siento que hay muchas condiciones que se deben unir para que esto funcione y me pregunto si tendré tanta suerte tratando de mover algún código Telerik Drag and Drop en MVVM.
En segundo lugar, parece un enfoque de rendimiento bastante pobre para recrear la lista de esa manera.
Por último, parece que esto sería más fácil en código detrás (aunque no estoy 100% seguro de que todavía no tenga que reconstruir esa lista).
¿Alguien tiene alguna idea sobre mi enfoque o tal vez incluso ... sugerencias para facilitar las cosas? ¿Me estoy perdiendo algo obvio aquí?
Gracias
-Driodilate:]
Bueno, eso no ayuda, pero me deja en la situación de no saber cómo conseguir el control enlazado a actualizar correctamente. Tenga en cuenta que no estoy agregando o eliminando elementos (eso funciona perfectamente sin el código adicional). Mi problema ocurre cuando estoy actualizando una propiedad en uno de los objetos que está en el ObservableCollection. – maulkye
Hmmmm, aunque me hiciste pensar. Podría simplemente eliminar el elemento seleccionado, actualizarlo y luego volver a agregarlo para que las actualizaciones automáticas funcionen. Aunque no estoy seguro de cómo afectará esto a la clasificación. – maulkye
Compruebe mi EDIT, hay otra pista que podría seguir :) – thmshd