我有两个ListBox,一个在另一个里面。并且两个ListBox都会根据用户请求动态添加项目。
每次单击按钮(下面的代码段中未显示)时,都会在列表框中添加一个新项目。每个新项目都包含一个新的列表框和其他项目。
我在内部列表框中有按钮,一个用于内部列表框的每个列表项。
使用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>
答案 0 :(得分:1)
为什么不直接在QuestionsListBox.DataContext
内使用ChoiceAddButton_Click
?您可以直接从代码中引用外部ListBox
,因为您已为其命名,DataContext
是可访问的属性。
private void ChoiceAddButton_Click(object sender, RoutedEventArgs e)
{
...
var outerLBDataContext= QuestionsListBox.DataContext;
...
}
使用您提供的XAML在演示解决方案中,这对我来说很好。
编辑2:
抱歉,没想到。Button
的{{1}}将是DataContext
,而不是Choice
集合。
您内心Choices
的{{1}} <{1}},ListBox
。DataContext
。您的Question
外Choices
为其TextBox
。绑定Question.Question
或DataContext
使Text
指向绑定目标。这里有一些棘手的XAML潜入ItemsSource
引用。
向您的外部DataContext
添加DataContext
:
ElementName
现在,在内部TextBox
中添加一个隐藏的TextBlock:
<TextBox Text="{Binding Question, Mode=TwoWay}" Grid.Row="0" HorizontalAlignment="Stretch" TextWrapping="Wrap" ElementName="questionTextBox"/>
最后,在事件处理程序中,您可以在树中导航以获取该引用:
ListBox
我想指出,这不是一个优雅的解决方案。然而,它是一个全UI解决方案,可能是一个有用的东西。但更好的设计是在 <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
}
}
}
(或其他任何名称)类中包含Parent
引用并使用它。然后就像使用适当的类型转换调用Choice
一样简单。这样,您的代码就变得更易于阅读和维护。
答案 1 :(得分:0)
您可以在包含数据模型订阅的内部模型中添加一个事件,然后将其添加到“选择”集合中,并以相应的方式传递相关信息。
答案 2 :(得分:0)
是否有必要在解决方案中使用Button控件?
如果未修复,则可以使用下面<Image Source="/Images/choices.add.png" Height="72" Width="72" HorizontalAlignment="Left" Stretch="Fill"/>
如果您使用Image控件然后与此结合使用,您可以将选择更改事件添加到内部列表框(ChoicesListBox)。然后在Handler中,您可以选择项目作为参数,并选择更改事件(SelectionChangedEventArgs)。
修改列表框并添加Selection changed事件处理程序,如下所示
<ListBox Name="ChoicesListBox" ItemsSource="{Binding Choices}" Grid.Row="1" HorizontalAlignment="Stretch" ItemContainerStyle="{StaticResource ListItem}" SelectionChanged="Items_SelectionChanged">
在page.xaml.cs中,您可以添加处理程序并访问该项目,如下所示
private void Items_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems[0] != null)
{
//Please use the casting to the Choices items type to make use.
var temp = (ChoicesItemViewModel)e.AddedItems[0];
}
}