【问题标题】:ListBox ItemsSource Doesn't UpdateListBox ItemsSource 不更新
【发布时间】:2011-07-21 06:36:08
【问题描述】:

我面临与 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);*/

        }
    }

}

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

【问题讨论】:

    标签: c# wpf mvvm mvvm-toolkit


    【解决方案1】:

    使用observableCollection&lt;T&gt; 而不是List&lt;T&gt;

    MSDN DOC:

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

    【讨论】:

      【解决方案2】:

      属性列的设置器应该引发一个 PropertyChanged 事件。 实现 INotifyPropertyChanged 这样做:MSDN INotifyPropertyChanged

      我猜 MVVM Toolkit 提供了一种简单的方法(也许 ViewModelBase 已经实现了接口......)。

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

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

      【讨论】:

      • Vivien 是对的,你也应该考虑只初始化一次你的收藏。当您调用 GetColumns() 方法时,清除您的集合并向其中添加新项目。
      • 您好 Vivien 和 Blindmeis,感谢您的解决方案。正如所指出的,我正在扩展 ViewModelBase 以创建所示的 MainViewModel。因此我相信 INotifyPropertyChanged 已实现。此外,我没有清除收藏。我也会尝试这样做并让你知道。如果我说的是错误的,请纠正我。再次感谢。
      • 谢谢薇薇安。我会尝试并告诉你。非常感谢您提供的所有帮助
      • 嗨,Vivien,它成功了。非常感谢。问题中的代码存在一些错误,我相应地对其进行了编辑以反映更改。在 MVVM 工具包中,ViewModelBase 提供了 OnPropertyChanged("PropertyName") 方法,您可以调用该方法而不是调用子类中不允许的 PropertyChaged("PropertyName")。干杯。
      猜你喜欢
      • 1970-01-01
      • 2014-11-26
      • 2010-11-03
      • 1970-01-01
      • 2014-03-08
      • 1970-01-01
      • 1970-01-01
      • 2015-02-07
      • 1970-01-01
      相关资源
      最近更新 更多