我想在点击按钮时显示一些自定义内容(使用datatemplate):
<ContentControl x:Name="content" />
<Button Content="Test" Click="button_Click" />
按钮显示/隐藏此内容
VM _vm = new VM();
void button_Click(object sender, RoutedEventArgs e) =>
content.Content = content.Content == null ? _vm : null;
这是datatemplate:
<DataTemplate DataType="{x:Type local:VM}">
<ListBox ItemsSource="{Binding Items}" SelectionChanged="listBox_SelectionChanged">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="IsSelected" Value="{Binding IsSelected}" />
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
</DataTemplate>
事件处理程序:
void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e) =>
Title = "Items: " + ((ListBox)sender).Items.Count;
视图模型:
public class VM
{
public List<Item> Items { get; } = new List<Item> { new Item(), new Item(), new Item() };
}
public class Item
{
public bool IsSelected { get; set; }
}
问题:卸载datatemplate时,SelectionChanged
事件的ListBox
上升,没有任何项目。
我不想要这个活动。我不想看到&#34;项目:0&#34;选择一些东西并卸载datatemplate后。
问题:发生了什么以及如何防止这种情况发生?
注意:这是非常简短和简化的MCVE,即不是一切都很漂亮,尽管有一些关键点:datatemplate里面有ListBox
,它使用IsSelected
绑定,我需要摆脱它卸货时发生SelectionChanged
事件。
调用堆栈:
答案 0 :(得分:2)
这与设计完全一致。您通过单击列表框中的项目进行选择。卸载模板后,ItemsSource
绑定将断开连接,项目源将变为空。此时,当前选择不再有效(项目源中不存在该项目),因此清除选择。这是一个选择变化:选择从什么变为零。在这种情况下,该事件是预期。
很少需要订阅SelectionChanged
。将SelectedItem
绑定到视图模型上的属性通常会更好。只要选择发生变化,该属性就会更新。您可以回复该属性更改,而不是回复SelectionChanged
事件。
这种方法很好地避免了您所看到的问题。卸载模板后,SelectedItem
绑定将断开连接,因此您的视图模型将不再更新。因此,清除选择时,您将看不到最终更改。
如果您的ListBox
支持多项选择,则可以继续订阅SelectionChanged
。但是,不要查询listBoxItems
;相反,浏览_vm.Items
并查看IsSelected
设置为true
的项目。这应该告诉你实际的选择,并且结果不应该被卸载的模板影响。
您还可以通过检查处理程序中(sender as ListBox)?.ItemsSource
是否为null来确定是否已卸载模板。但是,这不是必要的。
答案 1 :(得分:0)
我认为这是因为你总是覆盖内容:
VM _vm = new VM();
void button_Click(object sender, RoutedEventArgs e) =>
content.Content = content.Content == null ? _vm : null;
将其更改为此选项,以便仅为列表分配一次,因此只会分配一次。
void button_Click(object sender, RoutedEventArgs e)
{
if (content.Content == null )
{
content.Content = _vm;
// I also recommend you add the event handler for the ListBox here so it's not fired until you have content.
}
}
答案 2 :(得分:0)
我认为listBox_SelectionChanged
当您卸载列表时会触发此事件,因为部分实际已更改,检查项目计数,如果为0,则将标题设置为默认值。
void listBox_SelectionChanged(object sender, SelectionChangedEventArgs e) =>
Title = (((ListBox)sender).Items.Count > 0)? "Items: " + ((ListBox)sender).Items.Count: "Your title";