ListBox ItemsSource 不更新

发布于 2024-10-25 20:57:38 字数 5673 浏览 1 评论 0原文

我面临着 ListBox 的 ItemsSource 相关问题。我正在使用 WPF MVVM 工具包版本 0.1 实现 MVVM。

我设置了一个 ListBox itemSource,当用户双击某个其他元素时进行更新(我在后面的代码中处理了事件并在那里执行了命令,因为不支持将命令绑定到特定事件)。此时,通过执行命令,将生成一个新的 ObservableCollection 项,并且 ListBox 的 ItemsSource 将相应更新。但目前还没有发生。 ListBox 不会动态更新。可能是什么问题?我附上相关代码供您参考。

XAML:

双击生成下一个列表的项目列表:

<ListBox Height="162" HorizontalAlignment="Left" Margin="10,38,0,0" Name="tablesViewList" VerticalAlignment="Top" Width="144" Background="Transparent" BorderBrush="#20EEE2E2" BorderThickness="5" Foreground="White" ItemsSource="{Binding Path=Tables}" SelectedValue="{Binding TableNameSelected, Mode=OneWayToSource}" MouseDoubleClick="tablesViewList_MouseDoubleClick"/>

当前未更新的第二个项目列表:

 <ListBox Height="153" HorizontalAlignment="Left" Margin="10,233,0,0" Name="columnList" VerticalAlignment="Top" Width="144" Background="Transparent" BorderBrush="#20EEE2E2" BorderThickness="5" Foreground="White" ItemsSource="{Binding Path=Columns, Mode=OneWay}" DisplayMemberPath="ColumnDiscriptor"></ListBox>

代码隐藏:

    private void tablesViewList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        MainViewModel currentViewModel = (MainViewModel)DataContext;

        MessageBox.Show("Before event command is executed");
        ICommand command = currentViewModel.PopulateColumns;
        command.Execute(null);

        MessageBox.Show(currentViewModel.TableNameSelected);
        //command.Execute();
    }

视图模型:

namespace QueryBuilderMVVM.ViewModels
{
//delegate void Del();

public class MainViewModel : ViewModelBase
{
    private DelegateCommand exitCommand;

    #region Constructor

    private ColumnsModel _columns; 

    public TablesModel Tables { get; set; }
    public ControllersModel Operators { get; set; }
    public ColumnsModel Columns {

        get { return _columns; }
        set {
            _columns = value;
            OnPropertyChanged("Columns");
        } 
    }

    public string TableNameSelected{get; set;}



    public MainViewModel()
    {
        Tables = TablesModel.Current;
        Operators = ControllersModel.Current;
        Columns = ColumnsModel.ListOfColumns;
    }

    #endregion

    public ICommand ExitCommand
    {
        get
        {
            if (exitCommand == null)
            {
                exitCommand = new DelegateCommand(Exit);
            }
            return exitCommand;
        }
    }

    private void Exit()
    {
        Application.Current.Shutdown();
    }






    //Del columnsPopulateDelegate = new MainViewModel().GetColumns;


    //Method to be assigned to the delegate
    //Creates an object of type ColumnsModel
    private void GetColumns() { 

         ColumnsModel.TableNameParam = TableNameSelected;
        Columns = ColumnsModel.ListOfColumns;
    }



    private ICommand _PopulateColumns;
    public ICommand PopulateColumns
    {
        get {

            if (_PopulateColumns == null) {

                _PopulateColumns = new DelegateCommand(GetColumns); // an action of type method is passed
            }

            return _PopulateColumns;
        }

    }


}

}

模型:

public class ColumnsModel : ObservableCollection<VisualQueryObject>
{

    private DataSourceMetaDataRetriever dataSourceTableMetadataObject;// base object to retrieve sql data
    private static ColumnsModel listOfColumns = null;
    private static object _threadLock = new Object();
    private static string tableNameParam = null;

    public static string TableNameParam
    {
        get { return ColumnsModel.tableNameParam; }
        set { ColumnsModel.tableNameParam = value; }
    }

    public static ColumnsModel ListOfColumns
    {
        get
        {
            lock (_threadLock)
                if (tableNameParam != null)
                    listOfColumns = new ColumnsModel(tableNameParam);

            return listOfColumns;
        }

    }


    public ColumnsModel(string tableName)
    {
        ColumnsModel.tableNameParam = tableName;
        Clear();

        try
        {
            dataSourceTableMetadataObject = new DataSourceMetaDataRetriever();

            List<ColumnDescriptionObject> columnsInTable = new List<ColumnDescriptionObject>();

            columnsInTable = dataSourceTableMetadataObject.getDataTableSchema("Provider=SQLOLEDB;Data Source=.;Integrated Security=SSPI;Initial Catalog=LogiwizUser", ColumnsModel.tableNameParam);

            //List<String> listOfTables = dataSourceTableMetadataObject.getDataBaseSchema("Provider=SQLOLEDB;Data Source=.;Integrated Security=SSPI;Initial Catalog=LogiwizUser");
            //List<String> listOfTables = dsm.getDataBaseSchema("G:/mytestexcel.xlsx", true);

            //ObservableCollection<VisualQueryObject> columnVisualQueryObjects = new ObservableCollection<VisualQueryObject>();

            foreach (ColumnDescriptionObject columnDescription in columnsInTable)
            {
                VisualQueryObject columnVisual = new VisualQueryObject();
                columnVisual.ColumnDiscriptor = columnDescription;
                columnVisual.LabelType = "column";

                Add(columnVisual);
            }



        }
        catch (QueryBuilderException ex)
        {
            /* Label exceptionLabel = new Label();
             exceptionLabel.Foreground = Brushes.White;
             exceptionLabel.Content = ex.ExceptionMessage;
             grid1.Children.Add(exceptionLabel);*/

        }
    }

}

非常感谢任何帮助。提前致谢。

I am facing a ListBox's ItemsSource related issue. I am implementing MVVM with WPF MVVM toolkit version 0.1.

I set one ListBox itemSource to update when a user double clicks on some other element (I handled the event in the code behind and executed the command there, since binding a command to specific events are not supported). At this point through the execution of the command a new ObservableCollection of items get generated and the ListBox's ItemsSource is intended to get updated accordingly. But it is not happening at the moment. ListBox does not update dynamically. What can be the problem? I am attaching relvent code for your reference.

XAML:

List of items which is doubled click to generate the next list:

<ListBox Height="162" HorizontalAlignment="Left" Margin="10,38,0,0" Name="tablesViewList" VerticalAlignment="Top" Width="144" Background="Transparent" BorderBrush="#20EEE2E2" BorderThickness="5" Foreground="White" ItemsSource="{Binding Path=Tables}" SelectedValue="{Binding TableNameSelected, Mode=OneWayToSource}" MouseDoubleClick="tablesViewList_MouseDoubleClick"/>

Second list of items which currently does not get updated:

 <ListBox Height="153" HorizontalAlignment="Left" Margin="10,233,0,0" Name="columnList" VerticalAlignment="Top" Width="144" Background="Transparent" BorderBrush="#20EEE2E2" BorderThickness="5" Foreground="White" ItemsSource="{Binding Path=Columns, Mode=OneWay}" DisplayMemberPath="ColumnDiscriptor"></ListBox>

Code Behind:

    private void tablesViewList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        MainViewModel currentViewModel = (MainViewModel)DataContext;

        MessageBox.Show("Before event command is executed");
        ICommand command = currentViewModel.PopulateColumns;
        command.Execute(null);

        MessageBox.Show(currentViewModel.TableNameSelected);
        //command.Execute();
    }

View Model:

namespace QueryBuilderMVVM.ViewModels
{
//delegate void Del();

public class MainViewModel : ViewModelBase
{
    private DelegateCommand exitCommand;

    #region Constructor

    private ColumnsModel _columns; 

    public TablesModel Tables { get; set; }
    public ControllersModel Operators { get; set; }
    public ColumnsModel Columns {

        get { return _columns; }
        set {
            _columns = value;
            OnPropertyChanged("Columns");
        } 
    }

    public string TableNameSelected{get; set;}



    public MainViewModel()
    {
        Tables = TablesModel.Current;
        Operators = ControllersModel.Current;
        Columns = ColumnsModel.ListOfColumns;
    }

    #endregion

    public ICommand ExitCommand
    {
        get
        {
            if (exitCommand == null)
            {
                exitCommand = new DelegateCommand(Exit);
            }
            return exitCommand;
        }
    }

    private void Exit()
    {
        Application.Current.Shutdown();
    }






    //Del columnsPopulateDelegate = new MainViewModel().GetColumns;


    //Method to be assigned to the delegate
    //Creates an object of type ColumnsModel
    private void GetColumns() { 

         ColumnsModel.TableNameParam = TableNameSelected;
        Columns = ColumnsModel.ListOfColumns;
    }



    private ICommand _PopulateColumns;
    public ICommand PopulateColumns
    {
        get {

            if (_PopulateColumns == null) {

                _PopulateColumns = new DelegateCommand(GetColumns); // an action of type method is passed
            }

            return _PopulateColumns;
        }

    }


}

}

Model:

public class ColumnsModel : ObservableCollection<VisualQueryObject>
{

    private DataSourceMetaDataRetriever dataSourceTableMetadataObject;// base object to retrieve sql data
    private static ColumnsModel listOfColumns = null;
    private static object _threadLock = new Object();
    private static string tableNameParam = null;

    public static string TableNameParam
    {
        get { return ColumnsModel.tableNameParam; }
        set { ColumnsModel.tableNameParam = value; }
    }

    public static ColumnsModel ListOfColumns
    {
        get
        {
            lock (_threadLock)
                if (tableNameParam != null)
                    listOfColumns = new ColumnsModel(tableNameParam);

            return listOfColumns;
        }

    }


    public ColumnsModel(string tableName)
    {
        ColumnsModel.tableNameParam = tableName;
        Clear();

        try
        {
            dataSourceTableMetadataObject = new DataSourceMetaDataRetriever();

            List<ColumnDescriptionObject> columnsInTable = new List<ColumnDescriptionObject>();

            columnsInTable = dataSourceTableMetadataObject.getDataTableSchema("Provider=SQLOLEDB;Data Source=.;Integrated Security=SSPI;Initial Catalog=LogiwizUser", ColumnsModel.tableNameParam);

            //List<String> listOfTables = dataSourceTableMetadataObject.getDataBaseSchema("Provider=SQLOLEDB;Data Source=.;Integrated Security=SSPI;Initial Catalog=LogiwizUser");
            //List<String> listOfTables = dsm.getDataBaseSchema("G:/mytestexcel.xlsx", true);

            //ObservableCollection<VisualQueryObject> columnVisualQueryObjects = new ObservableCollection<VisualQueryObject>();

            foreach (ColumnDescriptionObject columnDescription in columnsInTable)
            {
                VisualQueryObject columnVisual = new VisualQueryObject();
                columnVisual.ColumnDiscriptor = columnDescription;
                columnVisual.LabelType = "column";

                Add(columnVisual);
            }



        }
        catch (QueryBuilderException ex)
        {
            /* Label exceptionLabel = new Label();
             exceptionLabel.Foreground = Brushes.White;
             exceptionLabel.Content = ex.ExceptionMessage;
             grid1.Children.Add(exceptionLabel);*/

        }
    }

}

Any help is greatly appreciated. Thanks in advance.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

歌入人心 2024-11-01 20:57:38

属性 Columns 的设置器应该引发 PropertyChanged 事件。
实现 INotifyPropertyChanged 来执行此操作: MSDN INotifyPropertyChanged

我猜是 MVVM Toolkit 提供了一种轻松完成此操作的方法(也许 ViewModelBase 已经实现了该接口...)。

编辑:实现 INotifyPropertyChanged 是不够的,您必须引发 INotifyPropertyChanged 创建的事件。你的财产应该是这样的:

private ColumnsModel _columns;
public ColumnsModel Columns 
{ 
  get { return _columns; } 
  set 
  { 
    _columns = value; 
    PropertyChanged("Columns"); 
  }
}

The setter of property Columns should raise a PropertyChanged event.
Implement INotifyPropertyChanged to do so : MSDN INotifyPropertyChanged

I guess MVVM Toolkit provides a way of doing so easily (perhaps ViewModelBase already implement the interface ...).

EDIT : Implementing INotifyPropertyChanged is not enough, you have to raise the event created by INotifyPropertyChanged. You property should look something like this :

private ColumnsModel _columns;
public ColumnsModel Columns 
{ 
  get { return _columns; } 
  set 
  { 
    _columns = value; 
    PropertyChanged("Columns"); 
  }
}
沉鱼一梦 2024-11-01 20:57:38

使用 observableCollection 而不是 List

MSDN 文档:

WPF 提供了 ObservableCollection 类,它是公开 INotifyCollectionChanged 接口的数据集合的内置实现。请注意,为了完全支持将数据值从源对象传输到目标,集合中支持可绑定属性的每个对象还必须实现 INotifyPropertyChanged 接口。有关更多信息,请参阅绑定源概述。

use an observableCollection<T> instead of a List<T>

MSDN DOC:

WPF provides the ObservableCollection class, which is a built-in implementation of a data collection that exposes the INotifyCollectionChanged interface. Note that to fully support transferring data values from source objects to targets, each object in your collection that supports bindable properties must also implement the INotifyPropertyChanged interface. For more information, see Binding Sources Overview.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文