简体   繁体   中英

Binding to a TextBox inside an ItemsControl ItemTemplate

The binding on my ItemsControl ItemsTemplate does not work. I've gone through some other similar stack overflow questions but I cannot figure out the problem with my binding. Can someone please show me what I am doing wrong with my binding?

Excerpt from my MainWindow's ViewModel;

private ObservableCollection<uint> words;
private uint word;
private int numberOfWords;

public ObservableCollection<uint> Words
{
    get
    {
        return this.words;
    }

    set
    {
        this.words = value;

        this.NotifyPropertyChanged(m => m.Words);
    }
}

public uint Word
{
    get
    {
        return this.word;
    }

    set
    {
        this.word = value;

        this.NotifyPropertyChanged(m => m.Word);
    }
}

public int NumberOfWords
{
    get
    {
        return this.numberOfWords;
    }

    set
    {
        this.numberOfWords = value;

        this.NotifyPropertyChanged(m => m.NumberOfWords);

        this.Words.Clear();

        for (uint x = 0; x < value; x++)
        {
            this.Words.Add(this.Word);
        }
    }
}

I have the below ItemsControl inside a user control. The MainWindow has its DataContext set to a ViewModel, which the ItemsControl uses. The ItemsSource binding works and I get however many textboxes I specify, but when putting a value in the TextBox, the binding does not work.

<ItemsControl Grid.Row="0" Grid.Column="1" Grid.RowSpan="8" ItemsSource="{Binding Words}">
<ItemsControl.ItemsPanel>
    <ItemsPanelTemplate>
        <WrapPanel />
    </ItemsPanelTemplate>
</ItemsControl.ItemsPanel>

<ItemsControl.ItemTemplate>
    <DataTemplate>
        <TextBox Text="{Binding Word}" Width="125" Height="25" />
    </DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

I saw one post that talks about using this type of binding below, but apparently, I do not understand FindAncestor, so I do not know if I am on the right track or not with this.

Text="{Binding Path=Word, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type ItemsControl}}}"

You cannot bind to elements in a collection and then change the element itself--you can only change properties of this element through the binding. In other words, given the following collection

[ "one", "two", "three" ]

through a binding such as

<TextBox Text="{Binding Words[0]} /> <!-- the word "one" is displayed in the tb -->

if you change "one" to "derp" you would not alter the collection to

[ "derp", "two", "three" ]

To apply this to your example, you would want to bind the collection to the ItemsControl, then in the template bind to each instance within the collection and change properties of this instance.

First, create your Model. This holds your data and is what you bind against in the UI.

public sealed class Word 
{ 
    public uint Value {get;set;}
}

Next, expose a collection of these on your View Model.

public sealed class ViewModel
{
    //create and fill in ctor
    public ObservableCollection<Word> WordsYo {get;private set;}
}

Next, bind your ItemsControl's ItemsSource to this property and bind elements in the template to the properties of Word:

<!-- Window.DataContext is set to an instance of ViewModel -->
<ItemsControl ItemsSource="{Binding WordsYo}">
<ItemsControl.ItemTemplate>
    <DataTemplate>
        <TextBox Text="{Binding Value}" />
    </DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>

The Aristocrats.

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