我的情况的一行摘要:当我选择一个详细项目时,主人仍然未被选中,所以我的错误细节项目。
假设两个ViewModel MasterList和DetailList是ObservableCollection,并尝试制作类似Explorer的GUI。左侧面板具有主 - 详细信息列表框,右侧面板将显示所选详细信息项之一。没有必要在右侧面板中显示主信息。
在我的左侧面板上,ListBox控件编码如下。
<ListBox x:Name="listBoxMaster" ItemsSource="{Binding Path=MasterList}" SelectionMode="Extended"
IsSynchronizedWithCurrentItem="True">
<ListBox.ItemTemplate>
<DataTemplate>
<ListBox x:Name="listBoxDetail" ItemsSource="{Binding Path=DetailList}" IsSynchronizedWithCurrentItem="True" />
</DataTemplate>
</ListBox.ItemTemplate>
请注意,我将IsSynchronizedWithCurrentItem =“True”设置为两个ListBox控件。
并在右侧面板中,将显示所选的详细信息项信息,如下所示。让我们简化一个名为DetailItemClass的详细项目类,它具有Name和Number属性。
试用1
<WrapPanel Name="wrapPanel1" DataContext="{Binding ElementName=listBoxMaster, Path=SelectedItem}">
<StackPanel DataContext="{Binding Path="DetailList/">
<TextBox Text="{Binding Path=Name}" />
<TextBox Text="{Binding Path=Number}" />
</StackPanel>
</WrapPanel>
发生了问题的GUI问题。 如果我们有。
当我选择M1-D2时,它可以工作。 之后,当我选择细节M2-D4时,它可以工作。 但是,在那之后,当我再次选择M1-D2时,它不起作用!预先选择的项目可能不会更新其主要选择。 此外,有时M2-D5选择在右侧面板中给出M1-D2。的 weired。
试用2
<WrapPanel Name="wrapPanel1" DataContext="{Binding Path=MasterList/DetailList/}">
<StackPanel>
<TextBox Text="{Binding Path=Name}" />
<TextBox Text="{Binding Path=Number}" />
</StackPanel>
</WrapPanel>
不行。虽然我将IsSynchronizedWithCurrentItem设置为true,但失败。我不知道为什么。
试用3
我只是摆脱DataContext XAML绑定并在代码隐藏中使用事件触发器,如下所示。
private void listBoxMaster_SelectionChanged(object sender, SelectionChangedEventArgs e)
{
if (e.AddedItems.Count == 1)
{
if (e.AddedItems[0] is DetailItemClass)
{
var element = (DetailItemClass)e.AddedItems[0];
wrapPanel1.DataContext = element;
}
}
}
它运行良好,但它不使用XAML绑定。
你能教我正确的约束表达吗?
答案 0 :(得分:0)
你有没有尝试过:
<WrapPanel Name="wrapPanel1" DataContext="{Binding ElementName=listBoxMaster, Path=SelectedItem}">
<StackPanel>
<TextBox Text="{Binding Path=DetailList.Name}" />
<TextBox Text="{Binding Path=DetailList.Number}" />
</StackPanel>
</WrapPanel>
或
<WrapPanel Name="wrapPanel1">
<StackPanel>
<TextBox Text="{Binding ElementName=listBoxMaster, Path=SelectedItem.DetailList.Name}" />
<TextBox Text="{Binding ElementName=listBoxMaster, Path=SelectedItem.DetailList.Number}" />
</StackPanel>
</WrapPanel>
这些是为了确保DataContext是否实际上是级联的。
答案 1 :(得分:0)
您不应使用多个列表框,因为会有许多与多项选择相关的问题。例如,您可以选择第一个列表框,但选择第二个列表框中的项目。
用ItemsControl
类替换外部列表框,使其不接收选择并且不可聚焦。
还将单个属性添加到根模型,该模型包含所有列表的单个选定项。我使用非常简单的模型重现了您的层次结构,在此示例中,此属性称为SelectedDetailItem
:
public class MasterListViewModel : INotifyPropertyChanged
{
public ObservableCollection<DetailListViewModel> MasterList { get; set; }
private ItemViewModel _selectedDetailItem;
public ItemViewModel SelectedDetailItem
{
get { return _selectedDetailItem; }
set
{
_selectedDetailItem = value;
OnPropertyChanged("SelectedDetailItem");
}
}
}
public class DetailListViewModel
{
public ObservableCollection<ItemViewModel> DetailList { get; set; }
}
public class ItemViewModel
{
public string Title { get; set; }
}
并将此属性绑定到两个控件:
<ItemsControl x:Name="listBoxMaster" ItemsSource="{Binding Path=MasterList}">
<ItemsControl.ItemTemplate>
<DataTemplate>
<ListBox x:Name="listBoxDetail" ItemsSource="{Binding Path=DetailList}" DisplayMemberPath="Title"
SelectedItem="{Binding DataContext.SelectedDetailItem, Mode=TwoWay, ElementName=listBoxMaster}"/>
</DataTemplate>
</ItemsControl.ItemTemplate>
</ItemsControl>
<WrapPanel Name="wrapPanel1" DataContext="{Binding SelectedDetailItem}" Grid.Column="1">
<TextBox Text="{Binding Path=Title}" />
</WrapPanel>