以下のコードビハインドがあります:
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として使用するだけだと思いました。
はい、DataContextを何らかの方法で設定する必要があります。設定されていない限り、ウィンドウにはDataContextがないため、DataContextはありません。コンストラクターでこれを行うと、ListBoxはDataContextを取得します。
public MainWindow()
{
InitializeComponent();
this.DataContext = this;
}
それ以外の場合は、バインディングでRelativeSource、ElementNameなどを使用できますが、=)は知っていると思います。
私は通常、ビューモデルをコンストラクターに渡し、渡されたビューモデルにデータコンテキストを設定します。その後、ObservableCollectionをビューの外に移動して、ビューモデルに配置できます。これにより、ビューとロジックが分離され、viewmodelコードの単体テストも可能になります。
public MainWindow(SomeViewModel viewModel)
{
DataContext = viewModel;
InitializeComponent();
}
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に追加されるたびにビューの背後にコードを置く必要なしに、ビューのバインディングを更新し続けます。