WPF リストボックスへのオブザーバブル コレクションのバインド




wpf listbox displaymemberpath (3)

はい、DataContextをどうにかして設定する必要があります。 DataContextはありません。Windowsには、設定されていない限りDataContextがありません。 ListBoxは、コンストラクタでこれを実行するとDataContextを取得します。

public MainWindow() 
{ 
    InitializeComponent(); 
    this.DataContext = this;
} 

それ以外の場合は、バインディングでRelativeSource、ElementNameなどを使用できますが、=を知っていたと思います)。

以下のコードビハインドがあります。

    public partial class MainWindow : Window
    {
        public MainWindow()
        {
            InitializeComponent();
        }

        ObservableCollection<int> sampleData = new ObservableCollection<int>();
        public ObservableCollection<int> SampleData
        {
            get
            {
                if (sampleData.Count <= 0)
                {
                    sampleData.Add(1);
                    sampleData.Add(2);
                    sampleData.Add(3);
                    sampleData.Add(4);
                }
                return sampleData;
            }
        }
    }

私のxamlは:

<Window x:Class="Sandbox.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        Title="MainWindow" Height="350" Width="525">
    <Grid>
        <ListBox ItemsSource="{Binding Path=SampleData}"/>
    </Grid>
</Window>

リストには、コレクション内の値(またはまったく何も)が表示されません。 誰かが私の間違いが何かを指摘することはできますか?

DataContextを明示的に設定する必要がありますか? 何も設定されていない場合、コントロールはそれ自体をDataContextとして使用することになります。


Answer #1

私は通常、コンストラクタにビューモデルを渡し、渡されたビューモデルにデータコンテキストを設定します。その後、ObservableCollectionをビューから移動してビューモデルに入れることができます。 これにより、ビューとロジックが分離され、ビューモデルコードを単体テストすることもできます。

public MainWindow(SomeViewModel viewModel) 
{ 
    DataContext = viewModel;

    InitializeComponent(); 
} 

Answer #2

MvvMパターンを使用してみてください。ビューでは、このようにListBoxを定義できます。

<ListBox ItemsSource="{Binding Path=Log, UpdateSourceTrigger=PropertyChanged}"/>

その場合、ビューはバインディングソースに関連するコードビハインドがなくても構いません。 関連するViewModelでは、次のように追加します。

public class ViewModel : ViewModelBase
{
    //...
    private ObservableCollection<string> p_Log;

    /// <summary>
    /// A log of a starting process
    /// </summary>
    public ObservableCollection<string> Log
    {
        get { return p_Log; }

        set
        {
            base.RaisePropertyChangingEvent("Log");
            p_Log.Add(value.ToString());
            base.RaisePropertyChangedEvent("Log");
        }
    }
    //....
    /// <summary>
    /// Initializes this view model.
    /// </summary>
    /// <param name="mainWindowViewModel">The view model for this application's main window.</param>
    private void Initialize(MainWindowViewModel mainWindowViewModel)
    {  
        //...
        p_Log = new ObservableCollection<string>();
    }

その後、ViewModelBaseで定義されたイベントは、新しい文字列が監視可能なコレクションp_logに追加されるたびに、ビューの背後にコードを追加することなく、ビュー内のバインディングを更新したままにします。





binding