Listbox使用ObservableCollection绑定到ItemSsource的麻烦

时间:2013-02-15 18:39:23

标签: c# wpf binding listbox

我无法绑定到List框控件的ItemsSource。我希望能够在用户执行某些操作时将文本行添加到“列表”框中。

SystemControls.xmal代码:

<ListBox Grid.Column="4"  Grid.Row="1" Grid.RowSpan="9" ItemsSource="{Binding ListBoxInput}" Height="165" HorizontalAlignment="Left" Name="listBox1" VerticalAlignment="Top" Width="250" ></ListBox>

SystemControls.xmal.cs代码段:

public partial class SystemControls : UserControl, ISystemControls
{
    IDriver _Driver;
    ISystemControls_VM _VM;
    public SystemControls(IDriver InDriver, ISystemControls_VM InVM)
    {
        _VM = InVM;
        _Driver = InDriver;
        DataContext = new SystemControls_VM(_Driver);
        InitializeComponent();
    }

SystemControls_VM.cs这应该是问题的核心所在。我已经让它在构造函数中工作,当我尝试在代码中稍后添加行时,例如当用户按下按钮时,它什么都不做:

public class SystemControls_VM:ViewModelBase, ISystemControls_VM
{
    IDriver _Driver;
    public ObservableCollection<string> _ListBoxInput = new ObservableCollection<string>();


    public SystemControls_VM(IDriver InDriver)
    {
        _Driver = InDriver;

        ListBoxInput.Add("test");//Works here
    }

    public ObservableCollection<string> ListBoxInput
    {
        get 
        { 
            return _ListBoxInput; 
        }
        set
        {
            _ListBoxInput = value;
            //OnPropertyChanged("ListBoxInput");
        }
    }




    public void OnButtonClickGetNextError()
    {
        ListBoxInput.Add("NextErrorClicked");//Does not work here                
    }

    public void OnButtonClickClear()
    {
        ListBoxInput.Clear();//Or Here
    }

如果需要OnPropertyChangedEventHandler:

namespace XXX.BaseClasses.BaseViewModels
{
    /// <summary>
    /// Provides common functionality for ViewModel classes
    /// </summary>
    public abstract class ViewModelBase : INotifyPropertyChanged
    {
    public event PropertyChangedEventHandler PropertyChanged = delegate{};

    protected void OnPropertyChanged(string propertyName)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(propertyName));
    }

    }    
}

2 个答案:

答案 0 :(得分:1)

1)您的公共属性称为 _ListBoxInput ,但您绑定到 ListBoxInput (无下划线)。使_ListBoxInput成为私有的。

2)因为集合已经可以观察,所以你不需要为列表框更新OnPropertyChanged。

3)看起来有些东西可能与您管理公共列表和私有ListBoxInput集合的方式不同。你正在调用。添加你的公共财产(它会立即在可观察的集合上引发一个事件)但是你最终也会将它添加到私人收藏中,然后你在公共财产上调用PropertyChanged。令人困惑的是:尝试下面的代码,看看它是如何工作的。 (请注意在您添加到_ListBoxInput的构造函数中,但是在添加到ListBoxInput的按钮单击事件中。)

4)尝试在构造函数中添加this.DataContext = this

public partial class MainWindow : Window {

    public ObservableCollection<string> ListBoxInput { get; private set; }

    public MainWindow() {
       InitializeComponent();
       this.ListBoxInput = new ObservableCollection<string>();
       this.DataContext = this;
    }

    private void AddListBoxEntry_Click(object sender, RoutedEventArgs e) {
       this.ListBoxInput.Add("Hello " + DateTime.Now.ToString());
    }
}

public partial class MainWindow : Window { public ObservableCollection<string> ListBoxInput { get; private set; } public MainWindow() { InitializeComponent(); this.ListBoxInput = new ObservableCollection<string>(); this.DataContext = this; } private void AddListBoxEntry_Click(object sender, RoutedEventArgs e) { this.ListBoxInput.Add("Hello " + DateTime.Now.ToString()); } }

并在xaml中,查看binding Mode

5)另外,另一种方法是你可以做你的INotifyPropertyChanged(我发现这个更干净)

<Grid>
    <Grid.ColumnDefinitions>
        <ColumnDefinition/>
        <ColumnDefinition/>
    </Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        <RowDefinition/>
    </Grid.RowDefinitions>

    <ListBox ItemsSource="{Binding ListBoxInput, Mode=OneWay}"
             Height="165" HorizontalAlignment="Left" 
             Name="listBox1" VerticalAlignment="Top" Width="250"  />

    <Button Grid.Column="1" Grid.Row="0" Name="AddListBoxEntry" 
             Margin="0,0,0,158" Click="AddListBoxEntry_Click" >
             <TextBlock>Add</TextBlock>
   </Button>
</Grid>

答案 1 :(得分:0)

所以得到了另一个消息来源的答案,但我想我会把它发布在这里以供参考。

所以发生的事情是我将数据上下文设置为SystemControls_VM的一个实例,而处理按钮单击的_VM referance则转到另一个SystemControls_VM实例。这也是为什么看起来按钮点击工作并且正在填充List而没有数据进入Control本身的原因

我更改了以下代码部分,它可以运行:

public partial class SystemControls : UserControl, ISystemControls
{
    IDriver _Driver;
    SystemControls_VM _VM;
        public SystemControls(IDriver InDriver, SystemControls_VM InVM)
        {
            _VM = InVM;
            _Driver = InDriver;
            DataContext = InVM;//new SystemControls_VM(_Driver);
            InitializeComponent();
        }