0

I have the below UI, which allows you to select a team in the left, then edit properties of the selected team on the right. Here's an example scenario demonstrating the issue:

  1. Select Dragon team
  2. Rename to Smaug, press save.
    1. "Dragon" in selection panel on left doesn't update to "Smaug". However, if I select another team, the reselect "Dragon", the textbox on the right side still (correctly) shows "Smaug". I'm pretty sure this means that the databound collection is correctly being updated.
  3. Close the Settings window, then reopen it.
  4. Left panel now (correctly) shows "Smaug".

The UI

The list of teams is being stored as an observable collection:

public class TeamList : ObservableCollection<Team>
{
    public TeamList() : base() { }
}

Team list on the left is being populated/bound:

SettingsWindow.xaml

<ListView ItemsSource="{Binding}" Grid.Column="0" Grid.Row="1" DisplayMemberPath="name"
          SelectionChanged="ListTeamSelected" SelectionMode="Single">
    <!--<ListView.ItemContainerStyle>
        <Style TargetType="ListViewItem">
            <Setter Property="Foreground" Value="{Binding color}" />
        </Style>
    </ListView.ItemContainerStyle>-->
</ListView>

SettingsWindow.xaml.cs

    public Team selectedTeam { get; set; }

    public SettingsWindow()
    {
        teams = TeamManager.Instance().teamList;
        this.DataContext = this.teams;
        if (!Application.Current.Resources.Contains("selectedTeam"))
            Application.Current.Resources.Add("selectedTeam", selectedTeam);
        InitializeComponent();
    }

Data on the right is being populated and saved:

SettingsWindow.xaml.cs

private void ClickSaveData(object sender, RoutedEventArgs e)
{
    selectedTeam.name = TeamName.Text;
    selectedTeam.color = PrimaryColorPicker.SelectedColor;
    selectedTeam.secondaryColor = SecondaryColorPicker.SelectedColor;
    saved = true;
}

private void ListTeamSelected(object sender, RoutedEventArgs e)
{
    selectedTeam = (Team)(sender as ListView).SelectedItems[0];
    TeamInfo.Visibility = Visibility.Visible;
    TeamName.Text = selectedTeam.name;
    PrimaryColorPicker.SelectedColor = selectedTeam.color;
    SecondaryColorPicker.SelectedColor = selectedTeam.secondaryColor;
}

Twofold question:

  1. Am I doing anything wrong with my databinding that's causing this issue? (I'm new at WPF)

  2. If not, is there a way for me to force the UI to update the list on the left? (this seems vaguely hacky to me)

Thank you in advance for any assistance!

Benjin
  • 2,264
  • 2
  • 25
  • 50
  • Do your properties implement INotifyPropertyChanged? – reggaeguitar Apr 04 '14 at 18:12
  • See http://stackoverflow.com/questions/1315621/implementing-inotifypropertychanged-does-a-better-way-exist and http://wpftutorial.net/INotifyPropertyChanged.html – reggaeguitar Apr 04 '14 at 18:18
  • Didn't realize that was a thing. Thanks! Would you like to post it as a response so I can mark it as the answer? – Benjin Apr 04 '14 at 18:23

2 Answers2

0

I didn't know to have the my Team class implement INotifyPropertyChanged. This link was very helpful and straightforward. A couple things to note for others who have never worked with data-binding before:

  1. You need getters and setters for all the properties you want to notify on in order to throw the event.

  2. You need to use private variables for holding the data itself, or the setter will trigger itself, throwing you into a stack overflow.

  3. The parameter for the event is the public name of the property that was changed, not the private name nor the value.

Thanks to @ReggaeGuitar for the answer!

Benjin
  • 2,264
  • 2
  • 25
  • 50
0

Your properties need to implement the INotifyPropertyChanged interface for databinding to work properly. For example (from http://wpftutorial.net/INotifyPropertyChanged.html)

private string _name;

public string Name
{
   get { return _name; }
   set 
   {
      _name = value;
      PropertyChanged("Name");
   }
}

private void PropertyChanged(string prop)
{
   if( PropertyChanged != null )
   {
      PropertyChanged(this, new PropertyChangedEventArgs(prop);
   }
}

I would highly recommend the MVVM Light Toolkit for any MVVM work though (https://mvvmlight.codeplex.com/). If you use the MVVM Light Toolkit then you can inherit from ViewModelBase and then implement your properties like this

    private string _orgId;
    public string OrgId
    {
        get { return _orgId; }
        set { _orgId = value; RaisePropertyChanged("OrgId"); }
    }
reggaeguitar
  • 1,795
  • 1
  • 27
  • 48