我在每个列表项中都有一堆包含contol的列表框。
<ListBox x:Name="projectList" IsSynchronizedWithCurrentItem="True">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}" />
<ListBox x:Name="taskList" ItemsSource="{Binding Tasks}">
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel>
<TextBlock Text="{Binding Name}" />
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<TextBox x:Name="textBoxTask" />
<Button
x:Name="ButtonAddNewTask"
Content="Test"
CommandParameter="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=DataContext}"
Click="ButtonAddNewTask_Click"
/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
当我点击列表框中的按钮时,我想在列表框中的列表框中添加一个新项目。我走到这一步。所以我的问题是如何获取文本框以及如何更新列表框?
这是我的点击事件
private void ButtonAddNewTask_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
Project proj = button.DataContext as Project;
if(proj.Tasks == null)
proj.Tasks = new List<Task>();
proj.Tasks.Add(new Task("Added Task"));
}
感谢名单
答案 0 :(得分:7)
最简单的解决方案可能是让一个对象代表外部ListBox中的每个项目。然后它将具有表示项目中每个控件的属性 - TextBox中的文本和ListBox中的项目(我认为,基于Click处理程序的任务列表)。
在Click处理程序中,您可以获取Button的DataContext(应该是外部列表集合中的项目),并将新任务添加到该对象的任务列表中。由于内部ListBox绑定到该列表,因此应使用新项更新它(假设它在添加项时发送事件,例如使用ObservableCollection)。
更新:根据您的评论,以下内容应该有效。
您的Project
课程应该有两个属性:
class Project
{
public string Name { get; set; }
private ObservableCollection<Task> tasks =
new ObservableCollection<Task>();
public IList<Task> Tasks
{
get { return this.tasks; }
}
}
Task
类只有一个属性 - 任务的名称。
ProjectView
类是Project
类的包装器(我从@ timothymcgrath的答案得到了这个想法)。它会跟踪新任务的名称以及当前的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
设置为上述类的实例:
public class Window1
{
public Window1()
{
this.InitializeComponent();
this.DataContext = this.model;
}
private Model model = new Model();
}
在XAML中,应修改绑定以绑定到上述属性:
<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>
最后,在按钮的单击处理程序中,创建任务。 DataContext
的{{1}}将是该项目的Button
。
ProjectView
由于所有控件都通过绑定获取其值,因此您无需访问控件本身来获取数据 - 只需使用已提供控件的数据结构。
将创建Task的代码移动到另一个类(可能是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
});
}
}
)可能会更好,但我只是将它留在事件处理程序中以便于我输入。
更新2 :修改了上述代码,将Project
属性移动到一个单独的类中,该类包含NewTaskName
的实例以供UI使用。这对你有用吗?
答案 1 :(得分:3)
我假设您的Project ListBox填充了Project对象的Collection。我将AddNewTask ICommand添加到Project类并通过属性公开它。然后将Add New Task按钮绑定到新的AddNewTask ICommand。对于CommandParameter,将TaskName放入其中并将其传递给命令。
尝试阅读一些MVVM(模型视图ViewModel),了解其工作原理的一些示例。它非常干净,效果很好。
答案 2 :(得分:0)
这个解决方案适用于手头的任务。
private void ButtonAddNewTask_Click(object sender, RoutedEventArgs e)
{
Button button = (Button)sender;
DependencyObject obj = LogicalTreeHelper.GetParent(button);
StackPanel item = obj as StackPanel;
TextBox textBox = item.FindName("textBoxTask") as TextBox;
ListBox listBox = item.FindName("taskList") as ListBox;
Project proj = button.DataContext as Project;
if(proj.Tasks == null)
proj.Tasks = new List<Task>();
listBox.ItemsSource = proj.Tasks;
listBox.Items.Refresh();
}