绑定到TabItem的DataGrid不使用MVVM

时间:2013-05-18 14:30:19

标签: c# wpf mvvm

我有一个小应用程序来帮助自己学习WPF和MVVM等。我一直在使用Josh Smith的例子找到here来构建我自己的应用程序。我已将应用程序添加TabItem s,但绑定到DataGrid的嵌入式ObservableCollection<ResourceViewModel>未显示任何数据,请参见下图:

Example

DataGrid是用蓝色包围的部分。由于某些原因,UserControl似乎也在标签中显示,但这不是我在这里问的问题。 UserControl包含DataGrid,其绑定如下

<DataGrid ItemsSource="{Binding Resources}" 
          dataAccess:DataGridTextSearch.SearchValue="{Binding ElementName=searchBox, 
              Path=Text, UpdateSourceTrigger=PropertyChanged}" 
          AlternatingRowBackground="Gainsboro" 
          AlternationCount="2" 
          HorizontalAlignment="Stretch"
          VerticalAlignment="Stretch">
...</DataGrid>

Resources属性在ViewModels名称空间中定义为

internal class ResourceDataViewModel : WorkspaceViewModel
{
    readonly ResourceDataRepository resourceRepository;
    public ObservableCollection<ResourceViewModel> Resources { get; private set; }
    ...
}

ResourceViewmodel保存DataGrid每行的信息。我可以确认填充了Resource属性。当我在MVVM之外使用相同的模型并以相同的方式填充Resource时。 有人可以向我提供并了解为什么会发生这种情况吗?

我试图设置绑定的显式路径

ItemsSource="{Binding Path=(viewModels:Resources)}" 

但这也行不通。谢谢你的时间。


编辑。解决评论。我通过

DataContext文件中设置了App.xaml.cs
protected override void OnStartup(StartupEventArgs e)
{
    base.OnStartup(e);
    MainWindow window = new MainWindow();

    // Create the ViewModel to which 
    // the main window binds.
    MainWindowViewModel mainWindowViewModel = new MainWindowViewModel();

    // When the ViewModel asks to be closed, 
    // close the window.
    EventHandler handler = null;
    handler = delegate
    {
        mainWindowViewModel.RequestClose -= handler;
        window.Close();
    };
    mainWindowViewModel.RequestClose += handler;

    // Allow all controls in the window to 
    // bind to the ViewModel by setting the 
    // DataContext, which propagates down 
    // the element tree.
    window.DataContext = mainWindowViewModel;
    window.Show();
}

MainWindow

的XAML
<Window x:Class="ResourceStudio.Views.MainWindow"
        xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
        xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
        xmlns:viewModels="clr-namespace:ResourceStudio.ViewModels"
        xmlns:views="clr-namespace:ResourceStudio.Views"
        Title="MainWindow" Height="629.4" Width="814.4">
   <Window.Resources>
      <ResourceDictionary Source="MainWindowResources.xaml" />
   </Window.Resources>
   <Grid>
      <Grid.ColumnDefinitions>
         <ColumnDefinition Width="284*"/>
         <ColumnDefinition Width="567*"/>
      </Grid.ColumnDefinitions>
      <Grid.RowDefinitions>
         <RowDefinition Height="48"/>
         <RowDefinition Height="*"/>
         <RowDefinition Height="24"/>
      </Grid.RowDefinitions>
      <DockPanel KeyboardNavigation.TabNavigation="None" 
                     Background="#FFBEC8D8" 
                 Grid.ColumnSpan="2" 
                 Margin="0,0,0.4,0">
         <Menu DockPanel.Dock="Top" 
                   Background="#FFF9F9F9" 
                   BorderBrush="Black" 
                   KeyboardNavigation.TabNavigation="Cycle">
            <MenuItem Header="_File">
               <MenuItem Header="Load _Resource..." 
                         Height="Auto" 
                         Command="{Binding LoadResourceCommand}"/>
               <MenuItem Header="_Add Language..." 
                         Height="Auto"/>
               <Separator/>
               <MenuItem Header="Close _Workspace" 
                         Height="Auto"
                         Command="{Binding CloseCommand}"/>
               <MenuItem Header="E_xit" 
                         Height="Auto" Command="{Binding CloseCommand}" />
            </MenuItem>
            <MenuItem Header="_Edit">
            </MenuItem>
         </Menu>
         <ToolBarTray DockPanel.Dock="Top" MaxHeight="24" Background="#FFF9F9F9">
            <ToolBar Background="#FFF9F9F9">
               <Button ToolBar.OverflowMode="Never">One</Button>
               <Button>Two</Button>
               <Button>Three</Button>
            </ToolBar>
         </ToolBarTray>
      </DockPanel>
      <Grid Grid.Row="1" Grid.ColumnSpan="2" Margin="0,0,0.4,23.6" Grid.RowSpan="2">
         <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="Auto"/>
            <ColumnDefinition Width="*"/>
         </Grid.ColumnDefinitions>
         <TabControl ItemsSource="{Binding Path=Workspaces}" 
                     Grid.Column="2" 
                     HorizontalAlignment="Stretch" 
                     VerticalAlignment="Stretch" 
                     TabStripPlacement="Top" 
                     Height="Auto" 
                     Width="Auto">
         </TabControl>
      </Grid>
      <StatusBar Grid.Row="2" Grid.ColumnSpan="2" Margin="0,0.4,0.4,-0.4">
         <StatusBarItem DockPanel.Dock="Left" Background="#FF007ACC" Margin="0,2,0,0">
            <TextBlock Text="Ready" Margin="5,0,0,0"/>
         </StatusBarItem>
      </StatusBar>
   </Grid>
</Window>

MainWindowResources.xaml的位置:

<ResourceDictionary 
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:viewModels="clr-namespace:ResourceStudio.ViewModels"
   xmlns:views="clr-namespace:ResourceStudio.Views"
   >
   <!--This template applies a ResourceControl view to an instance of the 
   ResourceDataViewModel class shown in the main window.-->
   <DataTemplate DataType="{x:Type viewModels:ResourceDataViewModel}">
      <views:ResourceControl/>
   </DataTemplate>

   <!--This template explains how to render the 'Workspace' 
   content area in the main window.-->
   <DataTemplate x:Key="WorkspacesTemplate">
      <TabControl 
      IsSynchronizedWithCurrentItem="True" 
      ItemsSource="{Binding}" 
      Margin="4"/>
   </DataTemplate>
</ResourceDictionary>

ResourceControl.xaml的完整代码是:

<UserControl x:Class="ResourceStudio.Views.ResourceControl"
             xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
             xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
             xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
             xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
             xmlns:viewModels="clr-namespace:ResourceStudio.ViewModels" 
             xmlns:dataAccess="clr-namespace:ResourceStudio.DataAccess" 
             mc:Ignorable="d" d:DesignHeight="300" d:DesignWidth="300" Name="control">
   <DockPanel DataContext="{Binding ElementName=control}" HorizontalAlignment="Stretch" VerticalAlignment="Stretch">
      <TextBox Text="M"  DockPanel.Dock="Top" Name="searchBox" />
      <Grid DockPanel.Dock="Top">
         <Border BorderBrush="#FF007ACC" BorderThickness="2" HorizontalAlignment="Stretch" 
                 VerticalAlignment="Stretch">
            <DataGrid ItemsSource="{Binding Path=(viewModels:Resources)}" 
                      dataAccess:DataGridTextSearch.SearchValue="{Binding ElementName=searchBox, Path=Text, UpdateSourceTrigger=PropertyChanged}" 
                      AlternatingRowBackground="Gainsboro" AlternationCount="2" HorizontalAlignment="Stretch"
                      VerticalAlignment="Stretch">
               <DataGrid.Resources>
                  <dataAccess:SearchValueConverter x:Key="searchValueConverter"/>
                  <Style TargetType="{x:Type DataGridCell}">
                     <Setter Property="dataAccess:DataGridTextSearch.IsTextMatch">
                        <Setter.Value>
                           <MultiBinding Converter="{StaticResource searchValueConverter}">
                              <Binding RelativeSource="{RelativeSource Self}" Path="Content.Text" />
                              <Binding RelativeSource="{RelativeSource Self}" Path="(dataAccess:DataGridTextSearch.SearchValue)" />
                           </MultiBinding>
                        </Setter.Value>
                     </Setter>
                     <Style.Triggers>
                        <Trigger Property="dataAccess:DataGridTextSearch.IsTextMatch" Value="True">
                           <Setter Property="Background" Value="Orange" />
                        </Trigger>
                     </Style.Triggers>
                  </Style>
               </DataGrid.Resources>
               <DataGrid.CellStyle>
                  <Style TargetType="DataGridCell" BasedOn="{StaticResource {x:Type DataGridCell}}">
                     <Style.Triggers>
                        <Trigger Property="IsSelected" Value="True">
                           <Setter Property="Background" Value="#FF007ACC"/>
                           <Setter Property="Foreground" Value="White"/>
                        </Trigger>
                     </Style.Triggers>
                  </Style>
               </DataGrid.CellStyle>
            </DataGrid>
         </Border>
      </Grid>
   </DockPanel>
</UserControl>

TextBox绑定到DataGrid。当用户键入TextBoxDataGrid过滤器并突出显示包含所需文本的单元格时。然而,这不是问题,这个代码有效,它只是对我感兴趣的DataGrid的绑定。再次感谢巡回演出。

Edit2:根据@ dkozl的评论,我已从DataContext="{Binding ElementName=control}"声明中删除DockPanel,因此我们现在

<DockPanel HorizontalAlignment="Stretch" 
           VerticalAlignment="Stretch">
...

MainWindowResource.xaml我现在有

<ResourceDictionary 
   xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
   xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
   xmlns:viewModels="clr-namespace:ResourceStudio.ViewModels"
   xmlns:views="clr-namespace:ResourceStudio.Views"
   >
   <!--This template applies a ResourceControl view to an instance of the 
   ResourceDataViewModel class shown in the main window.-->
   <DataTemplate DataType="{x:Type viewModels:ResourceDataViewModel}">
      <views:ResourceControl DataContext="{Binding}"/>
   </DataTemplate>

   <!--This template explains how to render the 'Workspace' 
   content area in the main window.-->
   <DataTemplate x:Key="WorkspacesTemplate">
      <TabControl 
      IsSynchronizedWithCurrentItem="True" 
      ItemsSource="{Binding}" 
      Margin="4"/>
   </DataTemplate>
</ResourceDictionary>

这没效果。这是我DataGrid中的ResourceControl未填充。再次感谢您的时间,非常感谢...

1 个答案:

答案 0 :(得分:2)

您的UserControl DockPanel.DataContext绑定ResourceControl,而不是ResourceDataViewModel课程。您需要做的是在DataContext中绑定ResourceControl DataTemplate。要实现首先从DataContext="{Binding ElementName=control}"移除ResourceControl.DockPanel,然后通过ResourceControl.DataContext<views:ResourceControl DataContext={Binding}"/>绑定到您的对象。您还需要将DataGrid项绑定从ItemsSource="{Binding Path=(viewModels:Resources)}"更改为ItemsSource="{Binding Path=Resources}"

不是原始问题的一部分,但同一模板适用于标题页和标签内容,因为DataTemplate是特定于类型的,在这种情况下,标题标题内容和标签内容是相同的。要解决此问题,请删除DataTemplate类型的viewModels:ResourceDataViewModel并将其直接放入主TabControl

<TabControl.ContentTemplate>
   <DataTemplate>
      <views:ResourceControl DataContext={Binding}"/>
   </DataTemplat‌​e>
</TabControl.ContentTemplate>