2

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

    }    
}
4

2 回答 2

1

1)您的公共属性称为_ListBoxInput但您绑定到ListBoxInput (no underscore)。将 _ListBoxInput 设为私有。

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

3) 看起来您管理公共与私有 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 中,看看binding Mode

<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));
    }
}
于 2013-02-15T19:09:58.700 回答
0

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

所以发生的事情是,我正在将数据上下文设置为 SystemControls_VM 的一个实例,而处理按钮单击的 _VM 引用将转到 SystemControls_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();
        }
于 2013-02-15T20:39:19.360 回答