Gerenciando várias seleções com MVVM
-
03-07-2019 - |
Pergunta
Em minha viagem para a aprendizagem MVVM Eu já estabelecido algum entendimento básico do WPF e do padrão de ViewModel. Eu estou usando o seguinte abstração ao fornecer uma lista e estou interessado em um único item selecionado.
public ObservableCollection<OrderViewModel> Orders { get; private set; }
public ICollectionView OrdersView
{
get
{
if( _ordersView == null )
_ordersView = CollectionViewSource.GetDefaultView( Orders );
return _ordersView;
}
}
private ICollectionView _ordersView;
public OrderViewModel CurrentOrder
{
get { return OrdersView.CurrentItem as OrderViewModel; }
set { OrdersView.MoveCurrentTo( value ); }
}
I podem, em seguida, se ligam a OrdersView juntamente com o apoio de triagem e de filtragem para uma lista no WPF:
<ListView ItemsSource="{Binding Path=OrdersView}"
IsSynchronizedWithCurrentItem="True">
Isso funciona muito bem para vistas seleção única. Mas eu gostaria de também apoiar várias seleções na exibição e ter o ligamento modelo para a lista de itens selecionados.
Como é que eu ligam os ListView.SelectedItems para uma propriedade apoiador sobre o ViewModel?
Solução
Adicionar uma propriedade IsSelected
para o seu filho ViewModel (OrderViewModel
no seu caso):
public bool IsSelected { get; set; }
Bind a propriedade selecionada no recipiente para isso (para ListBox, neste caso):
<ListBox.ItemContainerStyle>
<Style TargetType="{x:Type ListBoxItem}">
<Setter Property="IsSelected" Value="{Binding Mode=TwoWay, Path=IsSelected}"/>
</Style>
</ListBox.ItemContainerStyle>
IsSelected
é atualizado para coincidir com o campo correspondente no recipiente.
Você pode obter as crianças selecionadas no modelo de vista, fazendo o seguinte:
public IEnumerable<OrderViewModel> SelectedOrders
{
get { return Orders.Where(o => o.IsSelected); }
}
Outras dicas
posso garantir-vos: SelectedItems
é realmente bindable como um XAML CommandParameter
Há uma solução simples para esse problema comum; para fazer o trabalho você deve seguir todas as seguintes regras:
-
A seguir sugestão de Ed Bola, em seu comando de ligação de dados XAML, definir o atributo
CommandParameter
ANTES o atributoCommand
. Esta muito demorado bug . -
Certifique-se de métodos
ICommand
eCanExecute
do seuExecute
tem um parâmetro do tipoobject
. Desta forma, você pode evitar silenciado exceções expressos que ocorrem sempre que tipoCommandParameter
da ligação de dados não coincide com o seu métodoCommand
tipo de parâmetro:private bool OnDeleteSelectedItemsCanExecute(object SelectedItems) { // Your code goes here } private bool OnDeleteSelectedItemsExecute(object SelectedItems) { // Your code goes here }
Por exemplo, você pode enviar imóvel ListView
um ListBox
/ de SelectedItems
a seus métodos ICommand
ou o ListView
/ isto ListBox
. Grande, não é?
Espero que isso impede que alguém passar a enorme quantidade de tempo que eu fiz para descobrir como receber SelectedItems
como parâmetro CanExecute
.
Pode-se tentar criar uma propriedade anexada.
Se o fizer, irá salvar um de adicionar a propriedade IsSelected
para cada lista que você bind. Eu tenho feito isso por ListBox
, mas pode ser modificado para uso um em uma lista.
<ListBox SelectionMode="Multiple"
local:ListBoxMultipleSelection.SelectedItems="{Binding SelectedItems}" >
Mais informações: WPF - Encadernação ListBox SelectedItems -. Anexado propriedade VS Estilo
Se você estiver usando MVVM-LIGHT você pode usar este padrão:
Não especialmente elegante, mas parece que ele deve ser confiável, pelo menos