【问题标题】:Binding to DataContext outside current ItemsSource context在当前 ItemsSource 上下文之外绑定到 DataContext
【发布时间】:2011-04-24 14:50:12
【问题描述】:

我有一个DataSet 绑定到Window.DataContext;我也有DataGrid

<DataGrid ItemsSource={Binding Tables[Items]}>
    <DataGrid.Columns>
        <DataGridTextBoxColumn Header={Binding Path=DataContext.Tables[Names]/Test, RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type Window}}} />
    </DataGrid.Columns>
</DataGrid>

基本上,我正在尝试将该列的标题绑定到数据表“名称”、列“测试”、第一行。

但是,我无法做到这一点。请注意,我可以在 DataGrid 之外很好地绑定它。 Grid 的 ItemsSource 更改了数据上下文,我不知道如何在外部引用原始 DataContext。

看来绑定成功了;但问题是 Window.DataContext 中 Tables[Names] 的当前项(第一行)丢失了。

如果我将 DataSet 设为静态并通过 {x:Static local:dataset} 访问它,那么一切正常。但是我不能使用静态数据集,因为会有多个实例(多用户)。

谁能指点我正确的方向?

【问题讨论】:

    标签: wpf data-binding datagrid itemssource relativesource


    【解决方案1】:

    我很确定您可以通过使用RelativeSource 绑定来完成您想做的事情。

    <DataGrid ItemsSource="{Binding StringCollection}" 
              AutoGenerateColumns="False">
      <DataGrid.Columns>
        <DataGridTextColumn Binding="{Binding}" />
        <DataGridTextColumn Binding="{
                              Binding RelativeSource={
                                RelativeSource FindAncestor, 
                                AncestorType={x:Type Window}},
                              Path=DataContext.SomethingOutsideDataContext}" />
      </DataGrid.Columns>
    </DataGrid>
    

    我在http://bitbucket.org/claus/wpf-bindingoutsidedatacontext做了一个简单的例子

    它允许您绑定到父窗口,在我的例子中,它具有视图模型作为数据上下文(带有SomethingOutsideDataContext 属性)。

    您应该知道,这仅适用于 WPF 而不适用于 Silverlight - Silverlight 中尚未实现“FindAncestor,AncestorType”的东西......我不确定除了使用静态资源之外是否还有其他方法.

    【讨论】:

    • 如果它不适合你,请添加一个你试图绑定的 Tables[Items] / Tables[Names] 对象结构的小例子,我会看到如果我可以使用它创建一个示例...
    • 还要确保您的祖先类型是 Window 类型,而不是 UserControl 类型,因为 DataContext 属性将呈现 null
    • 当我做这个确切的事情(但我绑定Visibility)时,我得到:System.Windows.Data Error: 4 : Cannot find source for binding with reference 'RelativeSource FindAncestor, AncestorType='System.Windows.Controls.DockPanel', AncestorLevel='1''. BindingExpression:Path=DataContext.IsFileMode; DataItem=null; target element is 'DataGridTextColumn' (HashCode=16991479); target property is 'Visibility' (type 'Visibility')。目前我用 CodeBehind 处理这个。
    【解决方案2】:

    不知道这是否适合您的情况,但您可以尝试以下方法: 1)给你的窗口一个名称属性,例如名称=ZeWindow。 2) 像这样绑定你的DataGridTextBoxColumn Header:

    <DataGridTextBoxColumn Header="{Binding Path=DataContext.Tables[Names]/Text, ElementName=ZeWindow}"/>
    

    所以基本上,不是绑定到 DataGridDataContext,而是绑定到 Name=ZeWindow 的 UIElementDataContext

    P.S.:我对 WPF 很陌生,所以这可能不适用于 Window,但我使用 UserControls 做了类似的事情

    【讨论】:

    • 我也试过这个。它给出的结果与我帖子中的 FindAncestor 方法相同。即:绑定成功,但原来DataContext的“CurrentItem”丢失了。我的问题的罪魁祸首是我试图引用另一个 DataTable 有它自己的 CurrentItem (row[0]);如果我只引用一个简单的属性,那么您的方法以及 FindAncestor 都可以正常工作。
    • 好的,我明白了,那么我很抱歉,但我不知道可能是什么问题。希望其他人会知道
    【解决方案3】:

    这实际上是预期的行为:DataGridCellDataContext 是整个行。

    所以你有 3 个解决方案: 要么你像这样在代码中添加你的绑定:

    在每个列的构造函数中:

    string source = String.Format(CultureInfo.InvariantCulture, "[{0}].", thisColumnIndex);
    base.Binding = new Binding(source + "Text");
    

    (您必须找到一种方法来获取“thisColumnIndex”。就我而言,我在创建列之后立即添加它们,我只是将“dataGridOwner.Columns.Count”放在那里)。

    或者...

    您可以找到一种方法来在每个单元格上获取所需的 dataContext(尝试过,但是当列/行虚拟化打开时它会严重混乱)

    或者...

    看看那里:

    Binding a cell object's property to a DataGridCell in WPF DataGrid

    我个人认为第一个更适合我的目的(因为无论如何我在代码后面添加了我的列),但这最终取决于你......


    就 columnHeaders 而言(并且只有 columnsHeaders,而不是行),您还可以探索“DataTemplate”方式:

    将列的标题设置为列本身(这样您就可以将列设置为标题的 DataContext)并使用 DataTemplate。

    例如:

    在每个列类中:

    private static DependencyProperty ColumnHeaderProperty = DependencyProperty.Register("ColumnHeader", typeof(MyDataGridColumnHeader), typeof(MyTextBoxColumn));
    public MyDataGridColumnHeader ColumnHeader
    {
        get { return (MyDataGridColumnHeader)(GetValue(ColumnHeaderProperty)); }
        set { SetValue(ColumnHeaderProperty, value); }
    }
    
    this.ColumnHeader = new MyDataGridColumnHeader();
    Header = this;
    

    在您的 dataGrid 的 xaml 中,类似:

    <DataGrid.ColumnHeaderStyle>
        <Style TargetType="{x:Type DataGridColumnHeader}">
            <Style.Setters>
                <Setter Property="HorizontalContentAlignment" Value="Stretch"/>
                <Setter Property="VerticalContentAlignment" Value="Stretch"/>
                <Setter Property="BorderThickness" Value="{Binding BorderThickness}" />
                <Setter Property="BorderBrush" Value="{StaticResource DataGridLinesBrush}" />
                <Setter Property="Background" Value="{StaticResource DataGridColumnHeaderBackground}" />
    
                <Setter Property="FontFamily" Value="{Binding ColumnHeader.Font.Family, TargetNullValue={StaticResource DefaultFontFamily}}" />
                <Setter Property="FontSize" Value="{Binding ColumnHeader.Font.Size, TargetNullValue={StaticResource DefaultFontSize}}" />
                <Setter Property="FontStyle" Value="{Binding ColumnHeader.Font.Style, TargetNullValue=Normal}" />
                <Setter Property="FontWeight" Value="{Binding ColumnHeader.Font.Weight, TargetNullValue=Bold}" />
                <Setter Property="Foreground" Value="{Binding ColumnHeader.Font.Brush, TargetNullValue={StaticResource DataGridColumnHeaderForeground}}" />
    
                <Setter Property="ContentTemplate">
                    <Setter.Value>
                        <DataTemplate>
                            <Grid Background="{Binding ColumnHeader.Background}">
                                <Grid.ColumnDefinitions>
                                    <ColumnDefinition Width="Auto" />
                                    <ColumnDefinition Width="*" />
                                    <ColumnDefinition Width="Auto" />
                                </Grid.ColumnDefinitions>
                                <Image Name="LeftImage" Grid.Column="0" Stretch="None" Margin="3, 0, 0, 0" Source="{Binding ColumnHeader.LeftImage}" VerticalAlignment="Center"/>
                                <Image Name="RightImage" Grid.Column="2" Stretch="None" Margin="0, 0, 5, 0" Source="{Binding ColumnHeader.RightImage}" VerticalAlignment="Center"/>
                                <TextBlock Name="HeaderText"
                                           Grid.Column="1"
                                           VerticalAlignment="Center"
                                           HorizontalAlignment="Center"
                                           TextDecorations="{Binding ColumnHeader.Font.Decorations}"
                                           Text="{Binding ColumnHeader.Text}" />
                            </Grid>
                        </DataTemplate>
                    </Setter.Value>
                </Setter>
            </Style.Setters>
        </Style>
    </DataGrid.ColumnHeaderStyle>
    

    当然,我的“MyDataGridColumnHeader”类包含此处引用的所有属性的定义。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2011-10-17
      • 2010-12-02
      • 1970-01-01
      • 1970-01-01
      • 2015-06-27
      • 2022-01-17
      • 2021-10-24
      • 2018-11-14
      • 1970-01-01
      相关资源
      最近更新 更多