1
votes

I am trying to bind a textbox inside itemtemplate of my listview. As itemssource, I am using ObservableCollection. I have tried binding itemtemplate to datacontext itself by {Binding},yet it gives me InvalidOperationException. Here is the related snippet

<ListView Name="listOrder" ItemsSource="{Binding OrderBys,UpdateSourceTrigger=PropertyChanged}" HorizontalContentAlignment="Stretch">
                            <ListView.ContextMenu>
                                <ContextMenu>
                                    <MenuItem Name="AddOrder" Header="Sıra Ekle" Click="AddOrder_Click" />
                                </ContextMenu>
                            </ListView.ContextMenu>
                            <ListView.ItemTemplate>
                                <DataTemplate>
                                    <TextBox FontSize="10" Text="{Binding}"></TextBox>
                                </DataTemplate>
                            </ListView.ItemTemplate>
                        </ListView>

Here is the related part from the ViewModel

public class ViewModel_ReportDesigner : ViewModelBase
{

    //Tables
    public List<string> Tables
    {
        get
        {
            Reporting.ReportUtils rr = new Reporting.ReportUtils();
            return rr.GetChildList("IGAEntities");
        }
    }

    private string _selectedTable;
    public string SelectedTable {
        get
        {
            return _selectedTable;
        }
        set
        {
            _selectedTable = value;
            RaisePropertyChangedEvent("SelectedTable");
            RaisePropertyChangedEvent("Fields");

        }
    }

    //Fields
    public ObservableCollection<string> Fields
    {
        get
        {
            Reporting.ReportUtils rr = new Reporting.ReportUtils();
            if (SelectedTable != null)
            {
                return new ObservableCollection<string>(rr.GetChildList(SelectedTable));
            }
            return null;
        }
    }


    //Number of Fields
    private int _NumberOfFields;
    public int NumberOfFields
    {
        get
        {
            return _NumberOfFields;
        }
        set
        {
            _NumberOfFields = value;
            RaisePropertyChangedEvent("NumberOfFields");
        }
    }

    public ObservableCollection<ReportField> getEmptyFieldList()
    {
        ObservableCollection<ReportField> list = new ObservableCollection<ReportField>();
        for (int i = 1; i <= _NumberOfFields; i++)
        {
            list.Add(new ReportField("''", i.ToString()));
        }
        return list;
    }

    //Groups
    private List<string> _Groups;
    public List<string> Groups
    {
        get
        {
            if (_Groups == null)
            {
                _Groups = new List<string>();
            }
            return _Groups;
        }set
        {
            _Groups = value;
            RaisePropertyChangedEvent("Groups");
        }
    }
    //TableCreators
    private ObservableCollection<TableCreator> _TableCreators;
    public ObservableCollection<TableCreator> TableCreators
    {
        get
        {
            if (_TableCreators == null)
                _TableCreators = new ObservableCollection<TableCreator>();  
            return _TableCreators;
        }
        set
        {
            _TableCreators = value;
            RaisePropertyChangedEvent("TableCreators");
        }
    }

    private TableCreator _SelectedTableCreator;
    public TableCreator SelectedTableCreator
    {
        get
        {
            return _SelectedTableCreator;
        }
        set
        {
            _SelectedTableCreator = value;
            RaisePropertyChangedEvent("SelectedTableCreator");
        }
    }

    internal void RaiseChanged(string v)
    {
        RaisePropertyChangedEvent(v);
    }
}

Actually listview i am talking about is inside another listview. To make it all clear. When i add item to parent listview, I create an empty List and bind it to child listview. Then from context menu i add related elements like this

vm.SelectedTableCreator.OrderBys.Add("");
        vm.RaiseChanged("TableCreators");

Edit: Now i realized that my binding is correct, only problem is that textbox change event will not fire after i change the text inside the textbox.

2
could you show viewModel and how do you set DataContext? - StepUp
I included the Viewmodel and made further explanation regarding this issue. - Kemal

2 Answers

1
votes

If Your Binding is correct, you have to set the Binding Mode from your textbox to "TwoWay"

Like:

 <TextBox FontSize="10" Text="{Binding bla, Mode=TwoWay}"></TextBox>

Because, if you don´t set a Mode, the standard Mode is Mode = OneTime

Here are the different Modes if you don´t know them.

0
votes

Now i realized that my binding is correct, only problem is that textbox change event will not fire after i change the text inside the textbox.

then you should implement INotifyPropertyChanged in your model class:

public class TableCreator:INotifyPropertyChanged
{

    private string yourVariable;
    public string YourVariable
    {
        get { return YourVariable; }
        set {
            YourVariable =value;
            OnPropertyChanged("YourVariable");
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

}

As MSDN says:

Cause INotifyPropertyChanged0 notifies clients(UI) that a property value has changed.

like in the following example:

public class Person:INotifyPropertyChanged
{
    public int IdPerson { get; set; }

    private string name;
    public string Name
    {
        get { return name; }
        set {
            name =value;
            OnPropertyChanged("Name");
        }
    }

    private string surname;
    public string SurName
    {
        get { return surname; }
        set
        {
            surname = value;
            OnPropertyChanged("SurName");
        }
    }        

    public event PropertyChangedEventHandler PropertyChanged;
    public void OnPropertyChanged(string propertyName)
    {
        if (PropertyChanged != null)
            PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

}