简体   繁体   中英

Loading listboxes inside tabitems - which event to use?

Lets say I have an application which comprises one window. Inside the window is a tabcontrol, with three tabitems. Inside each tabitem is a usercontrol.

In one tab I have Add color. In the next tab I have add Fruit. In the third tab I have relationships, where the user can add links between the fruit and the colors. This relationship is displayed in a listbox like:

Apple > Red
Pear  > Green

Below this in the same tab I have missing fruits listbox and a missing colors listbox... ie fruits or colors that have been added but not linked in the relationship. I should explain that this data is all stored in three seperate textfiles, fruits.txt, colors.txt and relationships.txt.

The problem I have is as follows. At the moment the populating of the listboxes etc is on Usercontrol_loaded event. It doesn't matter for fruit/colors, as after the add button is clicked, the list reloads. The problem is in the relationship screen.

Say the user runs the program, and clicks on the relationship tab to see what is linked. We'll say that the above example was already in the textfile. So that relationship shows up - and no missing fruits. The user then clicks the fruit tab and adds a fruit and then the color tab and adds a color. Then moves to the relationship tab. The usercontrol_loaded event has already occured, so these two new additions do not show in the listboxes.

If I move the code to GotFocus event, the user can't make selection in any listbox because it is constantly loading, as clicking fires the event.

Is there any other event or way I could have this refresh JUST when the tab has been "switched to", other than providing a refresh button?

Thanks for reading.

...

Edit 1: If I databind to a list of missing fruits which I build in the codebehind, I still have the same problem. I have to reload this list everytime they go jump off this tab and come back to it (because potentially they've added a fruit or a color, which is now missing).

You need to understand how MVVM and change notification works. You don't need to use events or code-behind at all if you're tracking all of this stuff in observable collections in view model classes that are bound to the UI.

As wwosik suggests, create a class that exposes public Colors , Fruits , and Relationships properties that are all observable collections. As s/he didn't suggest but probably should have, also expose public MissingColors and MissingFruits observable collections. Finally, expose public SelectedColor and SelectedFruit properties.

Create bound controls:

<ListBox ItemsSource="{Binding Colors}" SelectedItem="{Binding SelectedColor}"/>
<ListBox ItemsSource="{Binding Fruits}" SelectedItem="{Binding SelectedFruit}"/>
<ListBox ItemsSource="{Binding Relationships}"/>
<ListBox ItemsSource="{Binding MissingColors}"/>
<ListBox ItemsSource="{Binding MissingFruits}"/>

Implement an AddRelationship method that adds a new relationship consisting of the SelectedColor and SelectedFruit . It should also remove the color and fruit from the respective MissingColors and MissingFruits collections. Create a command that calls this method and bind it to something in the UI.

That's it. It doesn't matter what tab anything is on. It doesn't matter what order the user views things in. When the user adds a relationship, or a fruit, or a color, the UI will get updated.

You need to bind your listboxes to the data from your ViewModel. This way the WPF framework overtakes the detection of the moment when to update the data.

WPF is not WinForms. You don't populate ListBoxes by yourself.

You have

class MyData{
   ObservableCollection<Color> Colors;
   ObservableCollection<Fruit> Fruits;
   ObservableCollection<Pairs> Pairs;

   public void MatchCurrentSelection(){
        var selectedColor = CollectionViewSource.GetDefaultView(Colors).CurrentItem;
        var selectedFruit = CollectionViewSource.GetDefaultView(Fruits).CurrentItem;
        if(selectedColor != null && selectedFruit != null){
             Colors.Remove(selectedColor);
             Fruits.Remove(selectedFruit);
             Pairs.Add(new Pair(selectedColor, selectedFruit));
        }
   }
} 

ListBoxes

<ListBox ItemsSource="{Binding Colors}" IsSynchronizedWithCurrentItem="true"/>
<ListBox ItemsSource="{Binding Fruits}" IsSynchronizedWithCurrentItem="true"/>
<ListBox ItemsSource="{Binding Pairs}"/>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM