最も簡単な解決策は、おそらく1つの目的は、外側のリストボックス内の各項目を表す持っているだろう。次に、アイテム内の各コントロール、つまりTextBoxのテキスト、ListBoxのアイテム(Clickハンドラに基づいたタスクのリスト)を表すプロパティを持ちます。
Clickハンドラでは、ButtonのDataContext(外部リストのコレクション内の項目である必要があります)を取得し、そのオブジェクトのタスクリストに新しいTaskを追加できます。内側のListBoxはそのリストにバインドされているため、新しい項目で更新する必要があります(ObservableCollectionなどのアイテムが追加されたときにイベントを送信すると仮定して)。
更新:あなたのコメントに基づいて、以下が動作するはずです。 - タスクの名前を
class Project
{
public string Name { get; set; }
private ObservableCollection<Task> tasks =
new ObservableCollection<Task>();
public IList<Task> Tasks
{
get { return this.tasks; }
}
}
Task
クラスだけつのプロパティを持っています
あなたProject
クラスには、二つの特性を持っている必要があります。
ProjectView
クラスは、Project
クラスのラッパーです(このアイデアは@thothymcgrathの回答から得ました)。これは、新しいタスクの名前を追跡し、現在Project
:
class ProjectView : INotifyPropertyChanged
{
public Project Project { get; set; }
private string newTaskName = string.Empty;
public string NewTaskName
{
get { return this.newTaskName; }
set
{
this.newTaskName = value;
this.OnPropertyChanged("NewTaskName");
}
}
public event PropertyChangedEventHandler PropertyChanged;
private void OnPropertyChanged(string propName)
{
PropertyChangedEventHandler eh = this.PropertyChanged;
if(null != eh)
{
eh(this, new PropertyChangedEventArgs(propName));
}
}
}
あなたはDataContext
として使用される新しいクラスが必要になります。このような何か:コードビハインドで
class Model
{
private ObservableCollection<ProjectView> projects =
new ObservableCollection<ProjectView>();
public IList<ProjectView> Projects
{
get { return this.projects; }
}
}
、上記クラスのインスタンスへのオブジェクトのDataContext
を設定:XAMLで
public class Window1
{
public Window1()
{
this.InitializeComponent();
this.DataContext = this.model;
}
private Model model = new Model();
}
、バインディングはに結合するように改変されなければなりません上記のプロパティ:
<ListBox x:Name="projectList" IsSynchronizedWithCurrentItem="True"
ItemsSource="{Binding Path=Projects}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Project.Name}" />
<ListBox x:Name="taskList"
ItemsSource="{Binding Project.Tasks}"
DisplayMemberPath="Name" />
<TextBox x:Name="textBoxTask"
Text="{Binding Path=NewTaskName, UpdateSourceTrigger=PropertyChanged}"/>
<Button x:Name="ButtonAddNewTask" Content="Test"
Click="ButtonAddNewTask_Click" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
最後に、ボタンのクリックハンドラで、タスクを作成します。 Button
のDataContext
は、その項目のProjectView
になります。
private void ButtonAddNewTask_Click(object sender, RoutedEventArgs e)
{
Button btn = (Button)sender;
ProjectView curProject = btn.DataContext as Project;
if(null != curProject)
{
curProject.Project.Tasks.Add(new Task()
{
Name = curProject.NewTaskName
});
}
}
すべてのコントロールが結合することにより、それらの値を取得するので、あなたは、データを取得するには、コントロール自体にアクセスする必要はありません - ちょうど、すでにコントロールを供給しているデータ構造を使用します。
タスクを作成するコードを別のクラス(おそらくProject
)に移動する方が良いでしょうが、私は自分のパーツで簡単に入力できるようにイベントハンドラに残しました。
アップデート2:UIで使用するためProject
のインスタンスをラップ別のクラスにNewTaskName
プロパティを移動するために上記のコードを変更されました。これはあなたのためにうまくいくのですか?
「テキストボックスを取得する」と正確にはどういう意味ですか? – Joey
目的は、テキストボックスのテキストを使用してタスクを作成することでした。 TextBox newTaskTextBox =ここにはありません。 proj.Tasks.Add(新しいタスク(newTaskTextBox.Text)); –