繁体   English   中英

使用ObservableCollection绑定到ItemSource的列表框麻烦

[英]Listbox Trouble with Binding to ItemSource using a ObservableCollection

我在绑定到列表框控件的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));
    }

    }    
}

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

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

3)您管理公共ListBoxInput和私有ListBoxInput集合的方式似乎有些问题。 您正在调用.Add到您的公共属性上(这将立即在可观察的集合上引发一个事件),但是最终您也将其添加到私有集合中,然后在公共属性上调用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()); } } 

在xaml中,查看绑定模式

<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>

5)单独说明,这是您可以执行INotifyPropertyChanged的另一种方法(我找到了这种清洁器)

public abstract class ViewModelBase : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged = delegate{};

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

因此从另一个来源得到了答案,但想出我可以在这里发布以供参考。

因此发生的事情是,我将数据上下文设置为SystemControls_VM的一个实例,而处理按钮单击的_VM引用正在将SystemContexts_VM的另一个实例设置为数据上下文。 这就是为什么看起来单击按钮起作用并且填充了列表但没有数据进入控件本身的原因

我更改了以下代码部分,它可以正常工作:

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();
        }

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM