Dynamically created Binding does not work
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
...
}
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));
}
}
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.
精彩评论