尝试解开ViewModel时的绑定问题

时间:2018-08-16 19:07:28

标签: c# wpf mvvm tabcontrol

我从WPF开始,试图了解如何正确设置MVVM。目前,我有一个具有ListBox的UserControl。列表框包含一个复选框列表,当选中该复选框时,我要显示一个TabItem,其中包含与该复选框关联的用户控件。首先,我找到了一种创建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,则绑定错误消失,并出现带有适当标题的TabItem,但显然DataContext为空。

MainWindow.xaml.cs:

    ...            
    public MainWindow () {
        InitializeComponent();
        this.DataContext = new ViewModel();
    }

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时才会发生(如果我删除该部分,则输出中不会出现错误)。

1 个答案:

答案 0 :(得分:0)

该错误告诉您问题所在:

  在“对象”“ DataTemplate”上找不到

“ Items”属性   (HashCode = 22018304)'

您将TabControl.DataContext设置为DataTemplate。 DataTemplate没有Items属性,因此会出现错误。

您似乎希望ViewModel成为DataContext。因此,只需不在TabControl上设置DataContext,它就会继承其父级的DataContext。它将一直冒泡直到到达窗口,该窗口具有您在代码中设置的DataContext,即新的ViewModel()。