2

ListBox の ItemsSource 関連の問題に直面しています。WPF MVVM ツールキット バージョン 0.1 で MVVM を実装しています。

ユーザーが他の要素をダブルクリックしたときに更新する ListBox itemSource を 1 つ設定しました (コマンドを特定のイベントにバインドすることはサポートされていないため、コード ビハインドでイベントを処理し、そこでコマンドを実行しました)。この時点でコマンドを実行すると、アイテムの新しい 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"/>

現在更新されていない項目の 2 番目のリスト:

 <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);*/

        }
    }

}

どんな助けでも大歓迎です。前もって感謝します。

4

2 に答える 2

5

プロパティColumnsのセッターは、PropertyChangedイベントを発生させる必要があります。INotifyPropertyChangedを実装してこれを行います:MSDN INotifyPropertyChanged

MVVM Toolkitは、これを簡単に行う方法を提供していると思います(おそらく、ViewModelBaseはすでにインターフェイスを実装しています...)。

編集:INotifyPropertyChangedを実装するだけでは不十分であり、INotifyPropertyChangedによって作成されたイベントを発生させる必要があります。プロパティは次のようになります。

private ColumnsModel _columns;
public ColumnsModel Columns 
{ 
  get { return _columns; } 
  set 
  { 
    _columns = value; 
    PropertyChanged("Columns"); 
  }
}
于 2011-03-23T12:20:42.943 に答える
2

observableCollection<T>の代わりに を使用するList<T>

MSDN ドキュメント:

WPF は ObservableCollection クラスを提供します。これは、INotifyCollectionChanged インターフェイスを公開するデータ コレクションの組み込み実装で​​す。ソース オブジェクトからターゲットへのデータ値の転送を完全にサポートするには、バインド可能なプロパティをサポートするコレクション内の各オブジェクトも INotifyPropertyChanged インターフェイスを実装する必要があることに注意してください。詳細については、バインディング ソースの概要を参照してください。

于 2011-03-23T13:08:01.177 に答える