绑定到当前 ItemsSource 上下文之外的 DataContext

发布于 2024-09-27 13:01:38 字数 717 浏览 0 评论 0原文

我有一个绑定到 Window.DataContext 的 DataSet;我还有一个 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>

基本上,我试图将该列的标题绑定到 DataTable“Names”、“Test”列、第一行。

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

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

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

谁能指出我正确的方向吗?

I have a DataSet bound to the Window.DataContext; I also have a 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>

Basically, I'm trying to bind the Header of that column to DataTable "Names", Column "Test", first row.

However, I can't get it right. Note that I can bind it fine outside the DataGrid. The Grid's ItemsSource changes the data context and I don't know how to refer outside to the original DataContext.

It seems that the binding succeeds; but the problem is that the current item (first row) of the Tables[Names] in the Window.DataContext got lost.

If I make the DataSet static and access it via {x:Static local:dataset} then things work fine. But I can't use static datasets because there will be multiple instances (multi-user).

Can anyone please point me in the right direction?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

枫林﹌晚霞¤ 2024-10-04 13:01:38

我很确定您可以通过使用 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 - “FindAncestor、AncestorType”功能尚未在 Silverlight 中实现...我不确定除了使用静态资源之外是否还有其他方法。

I'm pretty sure you could do what you're trying to do by using RelativeSource binding.

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

I made a quick example at: http://bitbucket.org/claus/wpf-bindingoutsidedatacontext

It allows you to bind to the parent Window, which in my case has the viewmodel as datacontext (with the SomethingOutsideDataContext property on it).

You should be aware though, this will only work with WPF and not Silverlight - the 'FindAncestor, AncestorType' stuff has not been implemented in Silverlight yet... I'm not sure if there's another method, besides using static resources.

哭了丶谁疼 2024-10-04 13:01:38

不知道这是否适合你的情况,但你可以尝试这样的事情:
1) 为您的窗口指定一个名称属性,例如Name=ZeWindow。
2) 像这样绑定您的 DataGridTextBoxColumn 标头:

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

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

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

Don't know if this will work for you situation, but you could try something like this:
1) Give your Window a Name attribute e.g. Name=ZeWindow.
2) Bind your DataGridTextBoxColumn Header like this:

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

So basically, instead of binding to the DataContext of the DataGrid, you bind to the DataContext of the UIElement with Name=ZeWindow.

P.S.: I'm pretty new to WPF, so this might not work with the Window, but I did something similar using UserControls

-小熊_ 2024-10-04 13:01:38

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

所以你有3个解决方案:
要么您在代码后面添加绑定,如下所示:

在每个列的构造函数中:(

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

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

或者...

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

或者...

看看那里:

将单元格对象的属性绑定到 WPF DataGrid 中的 DataGridCell

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


就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”类包含此处引用的所有属性的定义。

希望这有帮助。

This is the expected behaviour actually: The DataContext for DataGridCell is the entireRow.

so you have 3 solutions:
either you add your binding in code behind like this:

in each Column's Constructor:

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

(you have to find a way to get the "thisColumnIndex". As far as I'm concerned, I add the columns right after I create them, si I simply put "dataGridOwner.Columns.Count" there).

or...

you can find a way to get the dataContext you want on each cell (tried that but it messes up badly when column/row virtualization is on)

or...

have a look there:

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

I personally find the first one to be the better for my purpose (since I add my columns in code behind anyway), but this is really up to you in the end...


As far as columnHeaders are concerned (and only columnsHeaders, not rows), you might also explore the "DataTemplate" way:

set the columns' header to the Column itself (that way you set the column as DataContext for the header) and use a DataTemplate.

e.g.:

in each column class:

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;

and in your dataGrid's xaml, something like:

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

of course, my "MyDataGridColumnHeader" class contains definitions for all the properties referenced here.

hope this helps.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文