1

I want to bind TextBlocks to a Modell. But it does not work and I have no idea why.

class GameModel : INotifyPropertyChanged {
string[] _teamNames;
 ...
public string teamName(int team)
{
  return _teamNames[team];
}

public void setTeamName(int team, string name)
{
  _teamNames[team] = name;
  OnPropertyChanged("teamName");
}

protected void OnPropertyChanged(string name) {
 PropertyChangedEventHandler handler = PropertyChanged;
 if (handler != null)
  {
     handler(this, new PropertyChangedEventArgs(name));
  }
}

And the code which creates the TextBoxes

for (int currCol = 0; currCol < teams; currCol++) {
  TextBlock teamNameBlock = new TextBlock();
  Binding myNameBinding = new Binding();
  myNameBinding.Source = myGame;
  myNameBinding.Path = new PropertyPath("teamName", currCol);
  myNameBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
  teamNameBlock.SetBinding(TextBlock.TextProperty, myNameBinding); //The name of the team bind to the TextBlock
...
}
H.B.
  • 166,899
  • 29
  • 327
  • 400
Tobi
  • 540
  • 7
  • 18
  • 1
    It may not be the only issue, but your teamName function is not a property. You should check the documentation about "indexed properties" – Jem Sep 30 '11 at 14:01
  • is there a possibility to bind a function result? – Tobi Sep 30 '11 at 14:20
  • No you have to bind to a property, but you can call a function in the property's "get{}" – Jem Sep 30 '11 at 15:48
  • 1
    It actually is possible to bind to a method using a Converter. See http://stackoverflow.com/questions/502250/bind-to-a-method-in-wpf for an example – Rachel Sep 30 '11 at 16:52

2 Answers2

1

I think the problem is you bind to

public string teamName(int team)
{
  return _teamNames[team];
}

what is team parameter and the moment of change? Who sets that parameter. Make something like this, instead:

    public string teamName
    {
      get 
      {
            return _teamNames[currTeam];
      }
    }

You bind to a property, which returns the team name based on currTeam index, which is settuped based on you app logic.

Hope this helps.

Tigran
  • 61,654
  • 8
  • 86
  • 123
  • Thanks, but I can't return an array. There are multiple team-names. Can I pass the currTeam-Parameter in a different way? – Tobi Sep 30 '11 at 14:12
  • Ok, I tried it. The Modell returns an array of Strings and the PropertyPath is 'PropertyPath("teamName[" + currCol + "]")' but there is still no effect. – Tobi Sep 30 '11 at 14:19
  • You are still trying to bind to a field. See this post: http://stackoverflow.com/questions/1481130/wpf-binding-to-local-variable – Bahri Gungor Sep 30 '11 at 14:30
  • @Tobi: looking on the code provided I don't see any need to return an array of strings. What you want, again based on code provided, is show inside textbox the current TeamName. Just bind it teamname property like in my answer, and on beyond that, change currTeam index to swicth between different team names available. – Tigran Sep 30 '11 at 14:39
  • Well, the number of teams is dynamical. So I have to bind values inside an array to the controls. `currTeam` is set from the elemen-bind-path – Tobi Sep 30 '11 at 15:00
1

Here's a full, working example. The idea is to use an indexed property to access the team names. Note how the binding path is created: PropertyPath("[" + currCol + "]") , and how the property change is notified: OnPropertyChanged("Item[]"); After the creation of controls, the name of the 3rd team is changed to "Marge" to test the binding.

using System;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;

namespace TestBinding
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public Window1()
        {
            InitializeComponent();      
        }

        public override void OnApplyTemplate()
        {
            base.OnApplyTemplate();
            CreateTeamControls();
            myGame[2] = "Marge";
        }

        void CreateTeamControls()
        {
            var panel = new StackPanel();
            this.Content = panel;
            int teams = myGame.TeamCount;

            for (int currCol = 0; currCol < teams; currCol++)
            {
                TextBlock teamNameBlock = new TextBlock();

                panel.Children.Add(teamNameBlock);

                Binding myNameBinding = new Binding();
                myNameBinding.Source = myGame;
                myNameBinding.Path = new PropertyPath("[" + currCol + "]");
                myNameBinding.UpdateSourceTrigger = UpdateSourceTrigger.PropertyChanged;
                teamNameBlock.SetBinding(TextBlock.TextProperty, myNameBinding);
            }
        }

        GameModel myGame = new GameModel();
    }
}

class GameModel : INotifyPropertyChanged 
{
    string[] _teamNames = new string[3];

    public int TeamCount { get { return _teamNames.Count(); } }

    public GameModel()
    {
        _teamNames[0] = "Bart";
        _teamNames[1] = "Lisa";
        _teamNames[2] = "Homer";
    }

    public string this[int TeamName]
    {
        get
        {
            return _teamNames[TeamName];
        }
        set
        {
            if (_teamNames[TeamName] != value)
            {
                _teamNames[TeamName] = value;
                OnPropertyChanged("Item[]");
            }
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;

    private void OnPropertyChanged(string propertyName)
    {
        var changedHandler = this.PropertyChanged;
        if (changedHandler != null)
            changedHandler(this, new PropertyChangedEventArgs(propertyName));
    }
}
Jem
  • 2,255
  • 18
  • 25