Reputation: 693
I am using WPF (C#, Visual Studio 2010, MVVM Light) and have an issue with three Listbox controls.
So here's the situation: I have three Listboxes. The first is a list of IDs which are 'examples'. The second is also a list of IDs which are 'related items'. What they are examples of and related items to are classes in my program which represent verbs (as in, of the language kind).
If you click on either of these two ListBoxes, it will populate a third ListBox. The two do not affect each other, only the third. The third does not affect the other two. The third only holds one item at a time.
It works well, except for one situation. Let's say that the 'examples' ListBox contains the IDs 100002 and 100003. Let's also say that the 'related items' ListBox contains the IDs 100004 and 100005. I click on 100002, and so the first ListBox's selected item becomes that. The third Listbox displays the details of 100002 (as it should). Then I click in the second Listbox, on 100004. That becomes the second Listbox's selected item, and the third Listbox displays 100004. Fine so far. But let's now say I want to go back to 100002 again for whatever reason. Since it's still the selected item in the first Listbox, clicking on it again has no effect. The setter in the view model is not even triggered so I can't do anything there. In fact I'm not sure what my options are in this situation. I did consider using the setter of the 'examples' to set the selected item of the 'related items' to be null and vice versa, but I realised that would cause an infinite loop.
I also tried using one variable to link to both of the first two ListBoxes' selected items, but that did not solve the issue.
I also tried the following:
private LanguageItemViewModel _selectedExampleOrRelatedItemTestVM = null;
public LanguageItemViewModel SelectedExampleOrRelatedItemTestVM
{
get { return _selectedExampleOrRelatedItemTestVM; }
set
{
if (_selectedExampleOrRelatedItemTestVM != value)
{
Mediator.EventMediator.Instance.PassLanguageItemAsExampleOrRelatedItem(value);
_selectedExampleOrRelatedItemTestVM = null;
RaisePropertyChanged("SelectedExampleOrRelatedItemTestVM");
}
}
}
So that, after the relevant event is fired, the variable itself is just set to null. This also does not work.
Perhaps there is someone out there with some advice, or even some avenues I've not considered? Thanks.
Upvotes: 0
Views: 209
Reputation: 1330
I have figured two options:
1) Setting your binding of ListBox.SelectedItem to your ViewModel to a OneWay binding, to avoid the infinite loop you mentioned when setting the ViewModel's property to null. But as it may not be something that you want, and maybe you need to change the SelectedItem via your ViewModel, the second approach comes in handy.
2) Calling a method of your ViewModel when user clicks on the ListBox, and sending the SelectedItem as parameter. Something like:
XAML
<Window>
...
<ListBox x:Name="ListBoxFirst" MouseUp="ListBox_OnMouseUp"/>
...
</Window>
and in your View's CodeBehind file:
private void ListBox_OnMouseUp(object sender, MouseButtonEventArgs e)
{
var viewModel = DataContext as YourViewModelType;
if (viewModel != null && ListBoxFirst.SelectedItem != null)
{
viewModel.YourImplementedMethod(ListBoxFirst.SelectedItem);
}
}
So this way every time that user clicks on the item again, the method will be called repeatedly.
In additon, you are also able to call the method directly from your XAML file via the help of BlendSDK libraries:
Edited XAML
<Window xmlns:i="http://schemas.microsoft.com/expression/2010/interactivity">
...
<ListBox x:Name="ListBoxFirst">
<i:Interaction.Triggers>
<i:EventTrigger EventName="MouseUp" SourceName="ListBoxFirst">
<i:InvokeCommandAction Command="{Binding YourViewModelCommand}"
CommandParameter="{Binding ElementName=ListBoxFirst, Path=SelectedItem}"/>
</i:EventTrigger>
</i:Interaction.Triggers>
</ListBox>
...
</Window>
Where Interactivity namespace resides in:
System.Windows.Interactivity
Good luck :)
Upvotes: 6