2010-03-11 22 views
5

Defino un headertemplate en un wpf groupbox y el enlace de datos no funciona. No entiendo por qué.WPF GroupBox HeaderTemplate y DataBinding

<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}}"> 
              </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> 

Respuesta

1

El GroupBox no tiene un miembro llamado "CurrentContract". Lo más probable es que quiera acceder a una propiedad llamada "CurrentContract" del ViewModel correspondiente? El modelo de vista es DataContext del GroupBox, así que hay que cambiar las rutas de enlace a algo como ...

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

Gracias.Creo que por defecto en el enlace de datos, wpf siempre obtiene datos de la propiedad DataContext. Parece que no está en la plantilla de datos. – Coolweb

+1

O, como alternativa, puede vincular el DataContext al encabezado haciendo algo como Header = "{Binding}" en su declaración de GroupBox. De esta forma, su DataTemplate funcionará como está. Ver mi respuesta para más detalles. – jpierson

1

la lección aprendida anteriormente es útil en general para DataTemplates, pero en realidad descubierto recientemente que hay una manera mejor para cambiar la cabecera de un cuadro de grupo:

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

de esta manera no hay necesidad de definir una fuente relativo en los enlaces.

También tenga en cuenta this issue con GroupBoxes y el encabezado.

+0

Configurar el contenido visual directamente en la propiedad del encabezado funciona bien, pero no hay ninguna razón para evitar el HeaderTemplate si usted entiende cómo funciona. Por favor vea mi respuesta para una explicación. – jpierson

21

El problema es que el HeaderTemplate se utiliza para crear plantillas de la cabecera de este modo dentro del HeaderTemplate su DataContext es lo que ates o asignar a la propiedad de su HeaderGroupBox.

Piense en la propiedad Header como casi como DataContext para el encabezado del control. Normalmente, la propiedad DataContext inhibe su valor desde su elemento principal, pero como no todos los controles tienen un Header, el encabezado está en blanco a menos que lo establezca.

Al vincular su encabezado explícitamente al DataContext actual Header="{Binding}" su ejemplo debería funcionar como esperaba. Para ayudar a ilustrar cómo funciona esto, he creado un ejemplo simple a continuación que muestra cómo el Header y el DataContext funcionan independientemente el uno del otro para proporcionar datos al cuerpo o al encabezado del 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> 

Esto dará lugar a una GroupBox que se parece a la siguiente.

GroupBox with templated header

creo que por defecto en databinding, WPF siempre obtiene los datos de la propiedad DataContext. Parece no en datatemplate

Su suposición es correcta sobre DataContext y funciona en el DataTemplate como he demostrado es sólo que en la plantilla de la cabecera de la DataContext es el valor de la propiedad de la cabecera y no el propio DataContext.

+2

+1, ¡esta información realmente ayuda con cómo funciona el encabezado en los cuadros de grupo! – Mas

+0

Tenga en cuenta que estas observaciones también son ciertas en general para cualquier HeaderedContentControl también. – jpierson

+0

Lo más importante de esta respuesta es que debe configurar el encabezado = "{Binding}" si va a utilizar HeaderTemplate. – stricq

3
<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> 

Sólo se propagan GroupBox CC al contenido DataTemplate ... funciona como un encanto ...

+0

Esto es lo más fácil, creo. Gracias. –

0

Esto es lo que funcionó para mí:

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