Je suis en train de refactoriser une application simple pour suivre MVVM et ma question est de savoir comment déplacer un événement SelectionChanged de mon code vers le viewModel. J'ai examiné quelques exemples d'éléments de liaison aux commandes, mais je ne les ai pas bien compris. Quelqu'un peut-il aider avec cela. Merci!
Quelqu'un peut-il fournir une solution en utilisant le code ci-dessous? Merci beaucoup!
public partial class MyAppView : Window
{
public MyAppView()
{
InitializeComponent();
this.DataContext = new MyAppViewModel ();
// Insert code required on object creation below this point.
}
private void contactsList_SelectionChanged(object sender, System.Windows.Controls.SelectionChangedEventArgs e)
{
//TODO: Add event handler implementation here.
//for each selected contact get the labels and put in collection
ObservableCollection<AggregatedLabelModel> contactListLabels = new ObservableCollection<AggregatedLabelModel>();
foreach (ContactListModel contactList in contactsList.SelectedItems)
{
foreach (AggregatedLabelModel aggLabel in contactList.AggLabels)
{
contactListLabels.Add(aggLabel);
}
}
//aggregate the contactListLabels by name
ListCollectionView selectedLabelsView = new ListCollectionView(contactListLabels);
selectedLabelsView.GroupDescriptions.Add(new PropertyGroupDescription("Name"));
tagsList.ItemsSource = selectedLabelsView.Groups;
}
}
Vous devez utiliser une variable EventTrigger
en combinaison avec InvokeCommandAction
de l'espace de noms Windows.Interactivity. Voici un exemple:
<ListBox ...>
<i:Interaction.Triggers>
<i:EventTrigger EventName="SelectionChanged">
<i:InvokeCommandAction Command="{Binding SelectedItemChangedCommand}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
Vous pouvez référencer System.Windows.Interactivity
en allant Add reference > Assemblies > Extensions
.
Et l’espace de nom i
complet est: xmlns:i="clr-namespace:System.Windows.Interactivity;Assembly=System.Windows.Interactivity"
.
Cette question a un problème similaire.
WPF MVVM: Les commandes sont faciles. Comment connecter View et ViewModel avec RoutedEvent
La façon dont je traite ce problème consiste à avoir une propriété SelectedItem dans le ViewModel, puis à lier le SelectedItem de votre ListBox ou quoi que ce soit à cette propriété.
Votre meilleur pari utilise Windows.Interactivity
. Utilisez EventTriggers
pour associer une ICommand
à une RoutedEvent
.
Voici un article pour vous aider à démarrer: Comportements et déclencheurs de Silverlight et WPF
Pour reformuler cela, vous devez changer votre façon de penser. Vous ne gérez plus un événement "sélection modifiée", mais stockez l'élément sélectionné dans votre modèle de vue. Vous utiliseriez ensuite une liaison de données bidirectionnelle de sorte que lorsque l'utilisateur sélectionne un élément, votre modèle de vue soit mis à jour et que, lorsque vous modifiez l'élément sélectionné, votre vue soit mise à jour.
<ListBox SelectionChanged="{eb:EventBinding Command=SelectedItemChangedCommand, CommandParameter=$e}">
</ListBox>
Commande
{eb: EventBinding} (modèle de dénomination simple pour rechercher la commande)
{eb: EventBinding Command = NomCommande}
CommandParameter
$ e (EventAgrs)
$ this ou $ this.Property
chaîne
Je suivrais la réponse dans cette question
Fondamentalement, votre modèle de vue contiendra une liste de tous vos éléments et une liste des éléments sélectionnés. Vous pouvez ensuite attacher un comportement à votre zone de liste qui gère votre liste d'éléments sélectionnés.
Cela signifie que vous n'avez rien dans le code derrière et que xaml est assez facile à suivre. Le comportement peut également être réutilisé ailleurs dans votre application.
<ListBox ItemsSource="{Binding AllItems}" Demo:SelectedItems.Items="{Binding SelectedItems}" SelectionMode="Multiple" />
Parfois, la solution d'un événement de liaison à une commande via le déclencheur d'interactivité ne fonctionne pas, lorsqu'il est nécessaire de lier l'événement de usercontrol personnalisé . Dans ce cas, vous pouvez utiliser un comportement personnalisé.
Déclarez un comportement contraignant comme:
public class PageChangedBehavior
{
#region Attached property
public static ICommand PageChangedCommand(DependencyObject obj)
{
return (ICommand)obj.GetValue(PageChangedCommandProperty);
}
public static void SetPageChangedCommand(DependencyObject obj, ICommand value)
{
obj.SetValue(PageChangedCommandProperty, value);
}
public static readonly DependencyProperty PageChangedCommandProperty =
DependencyProperty.RegisterAttached("PageChangedCommand", typeof(ICommand), typeof(PageChangedBehavior),
new PropertyMetadata(null, OnPageChanged));
#endregion
#region Attached property handler
private static void OnPageChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var control = d as PageControl;
if (control != null)
{
if (e.NewValue != null)
{
control.PageChanged += PageControl_PageChanged;
}
else
{
control.PageChanged -= PageControl_PageChanged;
}
}
}
static void PageControl_PageChanged(object sender, int page)
{
ICommand command = PageChangedCommand(sender as DependencyObject);
if (command != null)
{
command.Execute(page);
}
}
#endregion
}
Et ensuite, liez-le à la commande en xaml:
<controls:PageControl
Grid.Row="2"
CurrentPage="{Binding Path=UsersSearchModel.Page,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
PerPage="{Binding Path=UsersSearchModel.PageSize,Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}"
Count="{Binding Path=UsersSearchModel.SearchResults.TotalItemCount}"
behaviors:PageChangedBehavior.PageChangedCommand="{Binding PageChangedCommand}">
</controls:PageControl>
Considérez Microsoft.Xaml.Behaviors.Wpf , son propriétaire est Microsoft
que vous pouvez voir dans cette page.
System.Windows.Interactivity.WPF propriétaire est mthamil
, tout le monde peut me dire s'il est fiable?
Exemple de Microsoft.Xaml.Behaviors.Wpf
:
<UserControl ...
xmlns:behaviors="http://schemas.Microsoft.com/xaml/behaviors"
...>
<Button x:Name="button">
<behaviors:Interaction.Triggers>
<behaviors:EventTrigger EventName="Click" SourceObject="{Binding ElementName=button}">
<behaviors:InvokeCommandAction Command="{Binding ClickCommand}" />
</behaviors:EventTrigger>
</behaviors:Interaction.Triggers>
</Button>
</UserControl>
Comme @Cameron MacFarland le mentionne, je voudrais simplement une liaison bidirectionnelle à une propriété du viewModel. Dans le configurateur de propriétés, vous pouvez utiliser la logique dont vous avez besoin, telle que l'ajout à une liste de contacts, en fonction de vos besoins.
Cependant, je n'appellerais pas nécessairement la propriété 'SelectedItem', car viewModel ne devrait pas connaître le calque de vue et son interaction avec ses propriétés. Je l'appellerais quelque chose comme CurrentContact ou quelque chose comme ça.
Évidemment, c’est à moins que vous souhaitiez simplement créer des commandes comme exercice à pratiquer, etc.