Silverlight ListBox在ListBox中,如何知道单击了哪个按钮?
我有两个列表框,一个在另一个里面。两个列表框都会根据用户请求动态添加项目 每次单击按钮(下面的代码段中未显示)时,都会向列表框中添加一个新项。每个新项目都包括一个新的列表框和其他列表框 我在内部列表框中有按钮,每个按钮对应于内部列表框的每个列表项 使用Silverlight ListBox在ListBox中,如何知道单击了哪个按钮?,silverlight,xaml,windows-phone-7,data-binding,Silverlight,Xaml,Windows Phone 7,Data Binding,我有两个列表框,一个在另一个里面。两个列表框都会根据用户请求动态添加项目 每次单击按钮(下面的代码段中未显示)时,都会向列表框中添加一个新项。每个新项目都包括一个新的列表框和其他列表框 我在内部列表框中有按钮,每个按钮对应于内部列表框的每个列表项 使用DataContext,我可以找到绑定到内部列表项的数据,并对其进行更改,以便将更改反映到适当的列表项上 但是,我还需要对绑定到外部列表项的数据进行更改,该列表项对应于按钮。我怎么知道是哪一个 我想出了一个解决办法,我认为它不够优雅。通过对模型进行
DataContext
,我可以找到绑定到内部列表项的数据,并对其进行更改,以便将更改反映到适当的列表项上
但是,我还需要对绑定到外部列表项的数据进行更改,该列表项对应于按钮。我怎么知道是哪一个
我想出了一个解决办法,我认为它不够优雅。通过对模型进行更改,我可以让每个内部数据保存对外部数据的引用,这样我就可以找到绑定到外部列表项的数据。但这似乎不是一个合适的解决方案。你有什么建议吗
下面是xaml的代码片段。我把它简化了,希望它容易理解。我觉得你不必阅读全部代码
<ListBox Name="QuestionsListBox" HorizontalAlignment="Stretch" ItemContainerStyle="{StaticResource ListItem}" >
<ListBox.ItemTemplate>
<DataTemplate>
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<TextBox Text="{Binding Question, Mode=TwoWay}" Grid.Row="0" HorizontalAlignment="Stretch" TextWrapping="Wrap"/>
<ListBox Name="ChoicesListBox" ItemsSource="{Binding Choices}" Grid.Row="1" HorizontalAlignment="Stretch" ItemContainerStyle="{StaticResource ListItem}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Click="ChoiceAddButton_Click" Height="72" Width="72" HorizontalAlignment="Left" BorderBrush="Transparent">
<Button.Background>
<ImageBrush ImageSource="/Images/choices.add.png" Stretch="Fill" />
</Button.Background>
</Button>
<TextBox Text="{Binding Value, Mode=TwoWay}" HorizontalAlignment="Stretch" Grid.Column="1" Margin="-20,0" />
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
在将事件添加到“选项”集合之前,您可以向包含数据模型订阅的内部模型添加事件,并以这种方式传递相关信息。在解决方案中使用按钮控件是否有必要??
如果未修复,则可以使用下面指定的“图像控件”
如果使用图像控件,则可以将选择更改事件添加到内部列表框(ChoicesListBox)。然后,在处理程序中,您可以在selection changed事件(SelectionChangedEventArgs)中选择作为参数的项
修改列表框并添加Selection changed事件处理程序,如下所示
<ListBox Name="ChoicesListBox" ItemsSource="{Binding Choices}" Grid.Row="1" HorizontalAlignment="Stretch" ItemContainerStyle="{StaticResource ListItem}" SelectionChanged="Items_SelectionChanged">
为什么不直接使用
QuestionsListBox.DataContext
内ChoiceAddButton\u点击
?您有一种直接的方法从代码后面引用外部的列表框
,因为您给了它一个名称,DataContext
是一个可访问的属性
private void ChoiceAddButton_Click(object sender, RoutedEventArgs e)
{
...
var outerLBDataContext= QuestionsListBox.DataContext;
...
}
在使用您提供的XAML的演示解决方案中,这对我来说很好
编辑2:
对不起,我没在想。按钮
的数据上下文
将是一个选项
,而不是选项
集合
您的内部列表框
的数据上下文
不是问题
,而是选择
。您的外部文本框
包含问题。问题
作为其数据上下文
。绑定Text
或ItemsSource
使DataContext
指向绑定目标。这里有一点棘手的XAML,需要潜入DataContext
引用
将元素名称
添加到外部文本框
:
<TextBox Text="{Binding Question, Mode=TwoWay}" Grid.Row="0" HorizontalAlignment="Stretch" TextWrapping="Wrap" ElementName="questionTextBox"/>
<ListBox Name="ChoicesListBox" ItemsSource="{Binding Choices}" Grid.Row="1" HorizontalAlignment="Stretch" ItemContainerStyle="{StaticResource ListItem}">
<ListBox.ItemTemplate>
<DataTemplate>
<Grid HorizontalAlignment="Stretch">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Button Grid.Column="0" Click="ChoiceAddButton_Click" Height="72" Width="72" HorizontalAlignment="Left" BorderBrush="Transparent">
<Button.Background>
<ImageBrush ImageSource="/Images/choices.add.png" Stretch="Fill" />
</Button.Background>
</Button>
<TextBox Text="{Binding Value, Mode=TwoWay}" HorizontalAlignment="Stretch" Grid.Column="1" Margin="-20,0" />
<TextBlock Name="hiddenTextBlock" Visibility="Collapsed" DataContext="{Binding ElementName=questionTextBox, Path=DataContext}"
</Grid>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
最后,在事件处理程序中,您可以在树中导航以获取该引用:
private void ChoiceAddButton_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
if(btn == null) return; //won't happen when this method handles the event
Grid g = btn.Parent as Grid;
if(g!=null) // also unlikely to fail
{
TextBlock tb = g.FindName("hiddenTextBlock") as TextBlock;
if(tb!=null) // also unlikely to fail, but never hurts to be cautious
{
var currentQuestion = tb.DataContext;
// now you've got the DC you want
}
}
}
我想指出的是,这并不是一个真正优雅的解决方案。不过,这是一个全UI解决方案,可能是一件有用的事情。但更好的设计是在您的
选择
和选择列表
(或其他名称)类中包含父类
引用并使用它们。然后就可以通过适当的类型转换调用btn.DataContext.Parent.Parent
。这样,您的代码就更易于阅读和维护。您是否只需要引用外部列表框的DataContext
,您可以在ChoiceAddButton\u单击
,还是更复杂的内容?@深奥的是,这就是我想要的。我会尽快尝试。非常感谢。嗨,@Esteric,这对我不起作用。QuestionsListBox.DataContext返回null。我需要的应该是相关内部列表框的DataContext
,而不是外部列表框。对不起,我误解了你先前的评论。您有解决方案吗?如何设置问题列表框
的项目资源
,以及它绑定到什么类型的对象?在我的示例中,我将它绑定到表单构造函数中的一个可观测集合
,因此我认为您的做法肯定有所不同。我将编辑我的答案,并建议如何获取内部列表框
(绑定到选项
)的数据上下文。您需要从内部选择添加按钮\u单击,对吗?我不需要按钮的数据上下文。这是我节目中的一个选择。我不想要外部列表的itemsource。这是一个明显的问题集合。我想要内部列表的datacontext,这应该是一个问题。我将外部列表的itemsource设置为一组问题,内部列表的itemsource设置为一组选择(这是问题的一个成员)。我确实认为您使用的方式是最好的方式,但我的答案确实提供了一种方法,可以仅使用视图引用来执行您的请求,如果您愿意,可以自由使用。仅仅因为我认为某些东西是更好的设计,并不意味着你必须使用它,甚至它是。此外,只要您不需要使用按钮的DataContext
指向选项
,就可以跳过添加隐藏控件,直接将按钮的DataContext
指向问题文本框
。
private void ChoiceAddButton_Click(object sender, RoutedEventArgs e)
{
Button btn = sender as Button;
if(btn == null) return; //won't happen when this method handles the event
Grid g = btn.Parent as Grid;
if(g!=null) // also unlikely to fail
{
TextBlock tb = g.FindName("hiddenTextBlock") as TextBlock;
if(tb!=null) // also unlikely to fail, but never hurts to be cautious
{
var currentQuestion = tb.DataContext;
// now you've got the DC you want
}
}
}