【发布时间】:2018-08-16 19:07:27
【问题描述】:
我从 WPF 开始,并试图了解如何正确设置 MVVM。目前我有一个用户控件,它有一个列表框。 The Listbox contains a list of Checkboxes which when checked I want to display a TabItem containing a user control associated to that checkbox.首先,我找到了一种创建 CheckListBox here 的方法,但是现在当我尝试创建标签页时,我得到了与 TabControls ItemsSource 相关的绑定异常:
System.Windows.Data Error: 40 : BindingExpression path error: 'Items' property not found on 'object' ''DataTemplate' (HashCode=22018304)'. BindingExpression:Path=Items.CheckedItems; DataItem='DataTemplate' (HashCode=22018304); target element is 'TabControl' (Name='tc_TabItems'); target property is 'ItemsSource' (type 'IEnumerable')
System.Windows.Data Error: 40 : BindingExpression path error: 'selectedItem' property not found on 'object' ''DataTemplate' (HashCode=22018304)'. BindingExpression:Path=selectedItem; DataItem='DataTemplate' (HashCode=22018304); target element is 'TabControl' (Name='tc_TabItems'); target property is 'SelectedItem' (type 'Object')
我的 MainWindow.xaml:
<Window x:Class="CheckListBox.MainWindow"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:local="clr-namespace:CheckListBox"
Title="MainWindow" Height="350" Width="525">
<Window.Resources>
<DataTemplate DataType="{x:Type local:TabItemViewModel}">
<local:TabItemUserControl />
</DataTemplate>
<DataTemplate x:Key="TabHeader" DataType="{x:Type local:TabItemViewModel}">
<TextBlock Text="{Binding Value.Name}"/>
</DataTemplate>
</Window.Resources>
<Grid Background="#FFE5E5E5">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<ListBox ItemsSource="{Binding Items}" SelectedItem="{Binding selectedItem}" Margin="4" SelectionMode="Extended" >
<ListBox.ItemTemplate>
<DataTemplate>
<StackPanel Orientation="Horizontal">
<CheckBox Name="check" IsChecked="{Binding IsChecked, Mode=TwoWay}" Margin="3" VerticalAlignment="Center" />
<ContentPresenter Content="{Binding Value.Name}" Margin="1"/>
</StackPanel>
</DataTemplate>
</ListBox.ItemTemplate>
</ListBox>
<StackPanel Grid.Column="1" >
<TextBlock FontWeight="Bold" >Selected Items</TextBlock>
<ItemsControl Grid.Column="1" Margin="4" x:Name="items" ItemsSource="{Binding Path=Items.SelectedItems}" DisplayMemberPath="Value.Name" />
</StackPanel>
<TabControl Name="tc_TabItems" Grid.Column="2" TabStripPlacement="Right"
ItemsSource="{Binding Items.SelectedItems}"
SelectedItem="{Binding selectedItem}"
>
<TabControl.ItemTemplate>
<DataTemplate DataType="{x:Type local:TabItemViewModel}">
<TextBlock Text="{Binding Value.Name}"/>
</DataTemplate>
</TabControl.ItemTemplate>
<TabControl.DataContext>
<DataTemplate>
<TabItem Content="{Binding Value}"></TabItem>
</DataTemplate>
</TabControl.DataContext>
</TabControl>
</Grid>
如果我删除TabControl.DataContext,那么绑定错误就会消失,并且出现带有适当标题的 TabItems,但显然 DataContext 是空的。
MainWindow.xaml.cs:
...
public MainWindow () {
InitializeComponent();
this.DataContext = new ViewModel();
}
视图模型:
private TabItemViewModel _selectedItem;
private CheckableObservableCollection<TabItemViewModel> _items;
public CheckableObservableCollection<TabItemViewModel> Items { get { return _items; } set { SetField( ref _items, value ); } }
public TabItemViewModel selectedItem { get { return _selectedItem; } set {SetField(ref _selectedItem, value); }}
public ViewModel () {
//Items = new CheckableObservableCollection<TabItemUserControl> { "this", "is", "a", "test" };
Items = new CheckableObservableCollection<TabItemViewModel>();
Items.Add( new TabItemViewModel { Name = "Name", Temp = "Temp1" } );
Items.Add( new TabItemViewModel { Name = "Nameington", Temp = "Temp2" } );
Items.Add( new TabItemViewModel { Name = "NameNameington", Temp = "Temp3" } );
*我省略了 CheckableObservableCollection 和 CheckWrapper,因为它们与链接中的大部分相同。我觉得 TabItemViewModel 并不是真正必要的,因为它是一个可以在 ViewModel 示例中设置和使用的属性集合
为了澄清上述错误仅在存在TabControl.DataContext 时发生(如果我删除该部分,则输出中不会出现错误)。
【问题讨论】:
-
您正在指定一个具有
selectedItem路径和ViewModel类型上下文的绑定。你的ViewModel(你没有显示)有一个名为selectedItem的属性吗?如果不是,那至少可以解释这个错误。 -
@TypeIA 我编辑了我的问题以显示更多的 ViewModel 类,但是 ViewModel 确实有一个 selectedItem 和一个 Items 属性。
-
"但显然 DataContext 是空的" - 为什么它会是空的?它应该从它的父级 Grid 那里得到它。而 Grid 从它的父级 Window 那里得到它。然后在代码中将 Window 上的 DataContext 设置为 new ViewModel()。
-
@J.H.我想我想通了。所以我使用
TabControl.DataContext而不是TabControl.DataTemplate。通过使用DataContext,我假设我覆盖了在 Window 上设置的原始上下文,这不是我想要做的。 -
迈克,大声笑......这样的事情发生在我们所有人身上。
标签: c# wpf mvvm tabcontrol