How to properly bind ItemTemplate's TextBox te

2020-05-03 10:07发布

I have a List called Paths which stores string elements. In MainWindow, I create an ItemControl to display textboxes that should bind to string elements of Paths. For example, if Paths consists of two string elements "Hello" and "World", Main Window should display two textboxes, one displays "Hello" and one displays "World", and the binding should be in TwoWay. So how should I properly do the binding work?

Remarks: I know that I should use ObservableCollection and bind it to ItemControl's ItemSource but I don't know the proper way.

Main Window

<ItemsControl ItemsSource="{Binding PathsCollection}">>
        <ItemsControl.ItemsPanel>
              <ItemsPanelTemplate>
                     <StackPanel Orientation="Vertical"/>
               </ItemsPanelTemplate>
         </ItemsControl.ItemsPanel>
         <ItemsControl.ItemTemplate>
              <DataTemplate>
                   <TextBox Text="{Binding Path=?????, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
              </DataTemplate>
         </ItemsControl.ItemTemplate>
</ItemsControl>

DataContext

public class SomeClass
{
    private List<string> _paths;
    public List<string> Paths
    {
        get {return _paths;}
        set {_paths = value; }
    }
    public ObservableCollection<string> PathsCollection
    {
        get 
        { // return what????
        }
        set 
        {
        // set what????
        }
    }
}

Update 1

The expected effect is shown after I modified the code as follows:

<ItemsControl ItemsSource="{Binding PathsCollection,  UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">>
        <ItemsControl.ItemsPanel>
              <ItemsPanelTemplate>
                     <StackPanel Orientation="Vertical"/>
               </ItemsPanelTemplate>
         </ItemsControl.ItemsPanel>
         <ItemsControl.ItemTemplate>
              <DataTemplate>
                   <TextBox Text="{Binding ., Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
              </DataTemplate>
         </ItemsControl.ItemTemplate>
</ItemsControl>
public class SomeClass
{
    private List<string> _paths;
    public List<string> Paths
    {
        get {return _paths;}
        set {_paths = value; }
    }
    public ObservableCollection<string> PathsCollection
    {
        get 
        { 
             return new ObservableCollection<string>(Paths);
        }
        set 
        {
             Paths = value.ToList();
        }
    }
}

However, it just works at the first initialization of the application. It failed to change any string element of _paths when I add, remove or modify some text inside TextBox. Why?

标签: c# wpf
1条回答
SAY GOODBYE
2楼-- · 2020-05-03 10:25

Like Clemens already said, you need to create a class which represents you string. So for example you can define that class like:

public class PathItem : INotifyPropertyChanged
{
    private string path;
    public string Path
    {
        get { return path; }
        set
        {
            path = value;
            OnPropertyChanged();
        }
    }

    public event PropertyChangedEventHandler PropertyChanged;
    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
    {
        PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
    }
}

And in your C#-Class you can use that class like:

private ObservableCollection<PathItem> pathsCollection;
public ObservableCollection<PathItem> PathsCollection
{
    get { return pathsCollection ?? (pathsCollection = new ObservableCollection<PathItem>()); }
}

To add items to this collection you can use:

PathsCollection.Add(new PathItem { Path = "MyPath1" });

And your xaml than looks like:

<ItemsControl ItemsSource="{Binding PathsCollection,  UpdateSourceTrigger=PropertyChanged, Mode=TwoWay}">>
        <ItemsControl.ItemsPanel>
              <ItemsPanelTemplate>
                     <StackPanel Orientation="Vertical"/>
               </ItemsPanelTemplate>
         </ItemsControl.ItemsPanel>
         <ItemsControl.ItemTemplate>
              <DataTemplate>
                   <TextBox Text="{Binding Path, Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />
              </DataTemplate>
         </ItemsControl.ItemTemplate>
</ItemsControl>
查看更多
登录 后发表回答