2010-03-11 9 views
5

Ich definiere ein headertemplate in eine wpf groupbox und die Datenbindung funktioniert nicht. Ich verstehe nicht warum.WPF GroupBox HeaderTemplate und 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> 

Antwort

1

Das GroupBox hat kein Mitglied namens "CurrentContract". Höchstwahrscheinlich möchten Sie auf eine Eigenschaft namens "CurrentContract" aus dem entsprechenden ViewModel zugreifen ?! Das Ansichtsmodell ist das GroupBox Datacontext, so haben Sie die Bindung Wege zu so etwas wie ...

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

Dank.Ich denke, dass in der Datenbindung standardmäßig WPF Daten von der DataContext-Eigenschaft erhält. Scheint nicht in Datatemplate. – Coolweb

+1

Oder alternativ können Sie den DataContext an den Header binden, indem Sie etwas wie Header = "{Binding}" in Ihrer GroupBox-Deklaration machen. Auf diese Weise funktioniert Ihr DataTemplate wie es ist. Siehe meine Antwort für weitere Details. – jpierson

1

Die Lektion oben ist nützlich für die Datatemplates im Allgemeinen gelernt zu ändern, aber ich fand tatsächlich heraus vor kurzem gibt es eine bessere Art und Weise

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

auf diese Weise gibt es keine Notwendigkeit, eine relativ Quelle in den Bindungen zu definieren: die Kopfzeile einer groupbox zu ändern.

Bitte beachten Sie auch this issue mit GroupBoxen und der Kopfzeile.

+0

Setzen Sie visuellen Inhalt direkt auf die Header-Eigenschaft funktioniert gut, aber es gibt keinen Grund, die HeaderTemplate zu vermeiden, wenn Sie verstehen, wie es funktioniert. Bitte sehen Sie meine Antwort für eine Erklärung. – jpierson

21

Das Problem ist, dass die HeaderTemplate für Templating den Header verwendet wird somit innerhalb der HeaderTemplate Ihre DataContext ist, was Sie auf die Header Eigenschaft Ihres GroupBox binden oder zuweisen.

Denken Sie an die Header Eigenschaft als fast wie die DataContext für den Header des Steuerelements. Normalerweise enthält die Eigenschaft DataContext ihren Wert von ihrem übergeordneten Element, aber da nicht jedes Steuerelement eine Header hat, ist die Kopfzeile leer, es sei denn, Sie legen sie fest.

Indem Sie Ihren Header explizit an den aktuellen DataContext Header="{Binding}" binden, sollte Ihr Beispiel wie erwartet funktionieren. Um zu veranschaulichen, wie dies funktioniert, habe ich unten ein einfaches Beispiel erstellt, das zeigt, wie die Header und DataContext unabhängig voneinander arbeiten, um Daten entweder an den Rumpf oder den Header des Steuerelements zu liefern.

Dies ergibt eine GroupBox, die wie folgt aussieht.

GroupBox with templated header

Ich denke, dass die standardmäßig in databinding, wpf immer Daten von der DataContext Eigenschaft bekommt. Scheint nicht in datatemplate

Ihre Annahme richtig ist über DataContext und es funktioniert in den DataTemplate wie ich es ist nur, dass in der Vorlage Kopfzeile demonstriert habe die Datacontext der Wert aus der Header-Eigenschaft und nicht die Datacontext selbst.

+2

+1, diese Informationen helfen wirklich, wie der Header in Gruppenfeldern funktioniert! – Mas

+0

Beachten Sie, dass diese Beobachtungen auch allgemein für jedes HeaderedContentControl gelten. – jpierson

+0

Der wichtigste Weg von dieser Antwort ist, dass Sie Header = "{Binding}" setzen müssen, wenn Sie die HeaderTemplate verwenden wollen. – 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> 

propagieren einfach die GroupBox DC an den Datatemplate Inhalt ... wirkt wie ein Zauber ...

+0

Das ist das einfachste, denke ich. Vielen Dank. –

0

Dies ist, was für mich gearbeitet:

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