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