WPF GroupBox HeaderTemplate 和 DataBinding

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2425079/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-08 21:33:59  来源:igfitidea点击:

WPF GroupBox HeaderTemplate and DataBinding

wpfgroupbox

提问by Coolweb

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

我将 headertemplate 定义到 wpf groupbox 中,并且数据绑定不起作用。我不明白为什么。

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

采纳答案by gehho

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

GroupBox 没有名为“CurrentContract”的成员。最有可能的是,您想从相应的 ViewModel 访问一个名为“CurrentContract”的属性?!ViewModel 是 GroupBox 的 DataContext,因此您必须将绑定路径更改为...

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

回答by jpierson

The problem is that the HeaderTemplateis used for templating the Header thus within the HeaderTemplateyour DataContextis whatever you bind or assign to the Headerproperty of your GroupBox.

问题是HeaderTemplate用于模板化 Header 因此在HeaderTemplateyour 中DataContext是您绑定或分配给Header您的GroupBox.

Think of the Headerproperty as almost like the DataContextfor the header of the control. Normally the DataContextproperty inhierits its value from its parent but since not every control has a Headerthe Header is blank unless you set it.

将该Header属性视为几乎类似于DataContext控件标题的 。通常,该DataContext属性从其父级继承其值,但由于并非每个控件都有一个HeaderHeader 为空,除非您设置它。

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 Headerand DataContextwork independently from each other for providing data to either the body or header of the control.

通过将您的 Header 显式绑定到当前 DataContext,Header="{Binding}"您的示例应该可以按预期工作。为了帮助说明这是如何工作的,我在下面创建了一个简单的示例,该示例展示了HeaderDataContext相互独立的工作,以便为控件的主体或标题提供数据。

<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 GroupBoxthat looks like the following.

这将产生GroupBox如下所示的结果。

GroupBox with templated header

带有模板标题的 GroupBox

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

我认为默认情况下databinding,wpf 总是从DataContext属性中获取数据。好像不在datatemplate

Your assumption is correct about DataContextand it does work in the DataTemplateas 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.

您的假设是正确的DataContext,它确实适用于DataTemplate我已经证明的,只是在 Header 的模板中,DataContext 是来自 Header 属性的值,而不是 DataContext 本身。

回答by frankidoze

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

只需将 GroupBox DC 传播到 DataTemplate 内容......就像一个魅力......

回答by Andre Luus

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:

上面学到的教训通常对 DataTemplates 很有用,但我实际上最近发现有一种更好的方法来更改 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 issuewith GroupBoxes and the header.

另请注意GroupBoxes 和标题的此问题

回答by stricq

This is what worked for me:

这对我有用:

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