在ContentPresenter上设置Datacontext:ContentTemplate内部的绑定不起作用。

9

我正在学习WPF和MVVM模式,尝试构建类似日历的视图。 目前我有一个6行7列的网格。 第一行应该是标题,因此需要指定星期几,例如“星期一,星期二”等。 现在我在MonthView.xaml中有以下内容:

<Grid>
    <Grid.RowDefinitions>
        <RowDefinition Height="{Binding RowHeight}"/>
        <RowDefinition Height="{Binding RowHeight}"/>
        <RowDefinition Height="{Binding RowHeight}"/>
        <RowDefinition Height="{Binding RowHeight}"/>
        <RowDefinition Height="{Binding RowHeight}"/>
        <RowDefinition Height="{Binding RowHeight}"/>
        <RowDefinition Height="{Binding RowHeight}"/>
    </Grid.RowDefinitions>

    <Grid.ColumnDefinitions>
        <ColumnDefinition Width="{Binding CellWidth}"/>
        <ColumnDefinition Width="{Binding CellWidth}"/>
        <ColumnDefinition Width="{Binding CellWidth}"/>
        <ColumnDefinition Width="{Binding CellWidth}"/>
        <ColumnDefinition Width="{Binding CellWidth}"/>
        <ColumnDefinition Width="{Binding CellWidth}"/>
        <ColumnDefinition Width="{Binding CellWidth}"/>
    </Grid.ColumnDefinitions>

    <!-- Header Row-->
    <ContentPresenter Grid.Row="0" Grid.Column="0">
        <ContentPresenter.ContentTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding DaysOfWeek[0]}"/>
            </DataTemplate>
        </ContentPresenter.ContentTemplate>
    </ContentPresenter>
    <ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="1" DataContext="{Binding DaysOfWeek[1]}"/>
    <ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="2" DataContext="{Binding DaysOfWeek[2]}"/>
    <ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="3" DataContext="{Binding DaysOfWeek[3]}"/>
    <ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="4" DataContext="{Binding DaysOfWeek[4]}"/>
    <ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="5" DataContext="{Binding DaysOfWeek[5]}"/>
    <ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="6" DataContext="{Binding DaysOfWeek[6]}"/>

    <!-- 1st Row-->
    <ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="0"/>
    <ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="1"/>
    <ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="2"/>
    <ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="3"/>
    <ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="4"/>
    <ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="5"/>
    <ContentPresenter ContentTemplate="{StaticResource CalendarCellTemplate}" Grid.Row="1" Grid.Column="6"/>

在这里:你应该能看出这个模式了。
这是CalendarHeaderCellTemplate。
<DataTemplate x:Key="CalendarHeaderCellTemplate">
    <StackPanel Margin="5" Background="Blue">
        <TextBlock Text="{Binding}"></TextBlock>
    </StackPanel>
</DataTemplate>

以下是ViewModel的重要部分:

 public ObservableCollection<string> DaysOfWeek { get; private set; }
 public MonthViewModel()
    {  
        this.DaysOfWeek = new ObservableCollection<string> {DayOfWeek.Monday.ToString(), DayOfWeek.Tuesday.ToString(), DayOfWeek.Wednesday.ToString(), 
            DayOfWeek.Thursday.ToString(), DayOfWeek.Friday.ToString(), DayOfWeek.Saturday.ToString(), DayOfWeek.Sunday.ToString()};

    }

现在,无论我在哪里定义DataTemplate的ContentPresenter都不会在其TextBlock中显示任何内容,也不会在CalendarHeaderCellTemplate中显示。
有趣的是,在Visual Studio设计器中,除了第一个单元格(即具有内联模板的单元格)之外,所有内容都正确显示。
有人有建议吗?
注:内联模板主要是为了测试目的而完成的。
编辑: 与使用ContentPresenter相比,执行以下操作可以正常工作。也许我以错误的方式使用ContentPresenter?
 <StackPanel Grid.Row="0" Grid.Column="0">
     <TextBlock Text="{Binding DaysOfWeek[0]}"/>
 </StackPanel>

我想使用ContentPresenter的原因是每个单元格内容的DataTemplate最终不仅仅是一个文本框。
2个回答

24

尝试将你的ContentPresenter改为:

    <ContentPresenter Content="{Binding DaysOfWeek[0]}" Grid.Row="0" Grid.Column="0">
        <ContentPresenter.ContentTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding}"/>
            </DataTemplate>
        </ContentPresenter.ContentTemplate>
    </ContentPresenter>
或者
  <ContentPresenter Content="{Binding}" Grid.Row="0" Grid.Column="0">
        <ContentPresenter.ContentTemplate>
            <DataTemplate>
                <TextBlock Text="{Binding DaysOfWeek[0]}"/>
            </DataTemplate>
        </ContentPresenter.ContentTemplate>
    </ContentPresenter>

并且将您的 DataContext 替换为 Content,例如:

<ContentPresenter ContentTemplate="{StaticResource CalendarHeaderCellTemplate}" Grid.Row="0" Grid.Column="1" Content="{Binding DaysOfWeek[1]}"/>

1
太好了,这就解决了。只需要将DataContext更改为Content即可。我现在要去MSDN上查看ContentPresenter.Content属性 :-) - Gilles Radrizzi
@biju:当内容就是数据时,为什么我们需要设置“Content”? - Joshua Frank

5

尝试使用ContentControl而不是ContentPresenter

<Style x:Key="CalendarCell" TargetType="ContentControl">
  <Setter Property="Template">
    <Setter.Value>
      <ControlTemplate TargetType="ContentControl">
        <StackPanel Margin="5" Background="{TemplateBinding Background}">
          <TextBlock Text="{TemplateBinding Content}" 
                     Foreground="{TemplateBinding Foreground}" />
        </StackPanel>
      </ControlTemplate>
    </Setter.Value>
  </Setter>
</Style>

<!-- Header Row-->
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="{Binding DaysOfWeek[0]}" 
                Background="Blue" 
                Foreground="White" />
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="{Binding DaysOfWeek[1]}" 
                Background="Blue" 
                Foreground="White" 
                Grid.Column="1" />
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="{Binding DaysOfWeek[2]}" 
                Background="Blue" 
                Foreground="White" 
                Grid.Column="2"  />
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="{Binding DaysOfWeek[3]}" 
                Background="Blue" 
                Foreground="White" 
                Grid.Column="3"  />
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="{Binding DaysOfWeek[4]}" 
                Background="Blue" 
                Foreground="White" 
                Grid.Column="4"  />
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="{Binding DaysOfWeek[5]}" 
                Background="Blue" 
                Foreground="White" 
                Grid.Column="5"  />
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="{Binding DaysOfWeek[6]}" 
                Background="Blue" 
                Foreground="White" 
                Grid.Column="6"  />

<!-- 1st Row-->
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="" 
                Background="Wheat" 
                Foreground="Black" 
                Grid.Row="1"  />
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="" 
                Background="Wheat" 
                Foreground="Black" 
                Grid.Column="1" 
                Grid.Row="1"  />
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="" 
                Background="Wheat" 
                Foreground="Black" 
                Grid.Column="2" 
                Grid.Row="1"  />
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="" 
                Background="Wheat" 
                Foreground="Black" 
                Grid.Column="3" 
                Grid.Row="1"  />
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="" 
                Background="Wheat" 
                Foreground="Black" 
                Grid.Column="4" 
                Grid.Row="1"  />
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="" 
                Background="Wheat" 
                Foreground="Black" 
                Grid.Column="5" 
                Grid.Row="1"  />
<ContentControl Style="{StaticResource CalendarCell}" 
                Content="" 
                Background="Wheat" 
                Foreground="Black" 
                Grid.Column="6" 
                Grid.Row="1"  />

Dean的回答也解决了问题。现在我想知道哪一个答案更好,即哪个答案会让我以后拥有更多的灵活性? - Gilles Radrizzi
1
ContentPresenter确实是为在控件模板中使用而设计的,因此我建议使用ContentControl。 - Dean Chalk

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接