我无法绑定到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));
}
}
}
答案 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();
}