开发者

WPF GroupBox HeaderTemplate and DataBinding

I define a headertemplate into a wpf groupbox and the databinding doesn't work. I don't understand why.

<GroupBox>
<GroupBox.HeaderTemplate>
            <DataTemplate>
            <StackPanel Orientation="Horizontal" >
                <Image Source="/PopuAssuNetApplication.UI.Control;component/Images/Members.png" Width="24" />
                <TextBlock VerticalAlignment="Center">
                                <TextBlock.Text>
                                        <MultiBinding StringFormat="{x:Static Member=resx:Resources.PersonsInContractGroupBox}"> 
                                            <Binding Path="CurrentContract.Federation" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}">
                                            &开发者_C百科lt;/Binding>
                                            <Binding Path="CurrentContract.Type" Converter="{StaticResource contractTypeConverter}" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}">
                                            </Binding>
                                            <Binding Path="CurrentContract.Number" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}">
                                            </Binding>
                                        </MultiBinding>
                                    </TextBlock.Text>
                </TextBlock>
                <WpfComponent:WaitControl Margin="7,0,0,0" VerticalAlignment="Top" Width="24" Height="24" MarginCenter="4">
                    <WpfComponent:WaitControl.Style>
                        <Style>
                            <Style.Triggers>
                                <DataTrigger Binding="{Binding Path=IsMembersOfContractBusy, UpdateSourceTrigger=PropertyChanged, ElementName=PersonsInContract}" Value="true">
                                    <Setter Property="WpfComponent:WaitControl.Visibility" Value="Visible" />
                                </DataTrigger>
                                <DataTrigger Binding="{Binding Path=IsMembersOfContractBusy, UpdateSourceTrigger=PropertyChanged, ElementName=PersonsInContract}" Value="false">
                                    <Setter Property="WpfComponent:WaitControl.Visibility" Value="Collapsed" />
                                </DataTrigger>
                            </Style.Triggers>
                        </Style>
                    </WpfComponent:WaitControl.Style>
                </WpfComponent:WaitControl>
            </StackPanel>
                </DataTemplate>
        </GroupBox.HeaderTemplate>


The problem is that the HeaderTemplate is used for templating the Header thus within the HeaderTemplate your DataContext is whatever you bind or assign to the Header property of your GroupBox.

Think of the Header property as almost like the DataContext for the header of the control. Normally the DataContext property inherits its value from its parent but since not every control has a Header the Header is blank unless you set it.

By binding your Header explicitly to the current DataContext Header="{Binding}" your example should work as you expect. To help illustrate how this works I've created a simple example below that shows how the Header and DataContext work independently from each other for providing data to either the body or header of the control.

<GroupBox Header="HEADER TEXT" DataContext="BODY TEXT">
    <GroupBox.HeaderTemplate>
        <DataTemplate>
            <Button Content="{Binding}"
                    Background="LightGreen" />
        </DataTemplate>
    </GroupBox.HeaderTemplate>

    <CheckBox HorizontalAlignment="Center"
                VerticalAlignment="Center" Content="{Binding}" />
</GroupBox>

This will yield a GroupBox that looks like the following.

WPF GroupBox HeaderTemplate and DataBinding

I think that by default in databinding, wpf always gets data from the DataContext property. Seems not in datatemplate

Your assumption is correct about DataContext and it does work in the DataTemplate as I've demonstrated it's just that in the Header's template the DataContext is the value from the Header Property and not the DataContext itself.


The GroupBox does not have a member called "CurrentContract". Most probably, you want to accesss a property called "CurrentContract" from the corresponding ViewModel?! The ViewModel is the GroupBox's DataContext, so you have to change the Binding Paths to something like...

<Binding Path="DataContext.CurrentContract.Type" Converter="{StaticResource contractTypeConverter}" RelativeSource="{RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}">


    <GroupBox >
        <GroupBox.HeaderTemplate>
            <DataTemplate>
                    <RadioButton Content="myR"
                            IsChecked="{Binding rIsChecked, Mode=TwoWay}"
                            DataContext="{Binding DataContext, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type GroupBox}}}" />
            </DataTemplate>
        </GroupBox.HeaderTemplate>
        <GroupBox.Content>
            <Grid IsEnabled="{Binding rIsChecked}">
            </Grid>
        </GroupBox.Content>
    </GroupBox>

Just propagate the GroupBox DC to the DataTemplate content...works like a charm...


The lesson learned above is useful in general for DataTemplates, but I actually found out recently there is a better way to change the header of a groupbox:

<GroupBox>
    <GroupBox.Header>
        <CheckBox IsChecked="{Binding Path=mSomeBoolean}"/>
    </GroupBox.Header>
</GroupBox>

This way there is no need to define a relative source in the bindings.

Also please note this issue with GroupBoxes and the header.


This is what worked for me:

<HeaderedContentControl Header="{Binding}" Style="{StaticResource TallHeaderedContentStyle}">
  <HeaderedContentControl.HeaderTemplate>
    <DataTemplate>
      <TextBlock Text="{Binding Path=HeaderText"} />
    </DataTemplate>
  </HeaderedContentControl.HeaderTemplate>
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜