Привязка к DataContext вне текущего контекста ItemsSource - PullRequest
7 голосов
/ 13 октября 2010

У меня есть 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>

По сути, я пытаюсь привязать заголовок этого столбца к DataTable «Имена», столбец «Тест», первая строка.

Однако я не могу понять это правильно.Обратите внимание, что я могу связать это отлично за пределами DataGrid.ItemsSource Grid изменяет контекст данных, и я не знаю, как ссылаться снаружи на исходный DataContext.

Кажется, что привязка успешна;но проблема в том, что текущий элемент (первая строка) таблиц [Names] в Window.DataContext потерян.

Если я сделаю DataSet статическим и получу к нему доступ через {x: Static local: dataset}тогда все работает нормально.Но я не могу использовать статические наборы данных, потому что будет несколько экземпляров (многопользовательских).

Может кто-нибудь указать мне правильное направление?

Ответы [ 3 ]

12 голосов
/ 15 декабря 2010

Я почти уверен, что вы можете сделать то, что пытаетесь сделать, используя 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

Позволяет привязать к родительскому окну, которое в моем случае имеет viewmodel как datacontext (со свойством SomethingOutsideDataContext).

Вы должны знать, однако, что это будет работать только с WPF, а не с Silverlight - материал 'FindAncestor, AncestorType' еще не реализован в Silverlight ... Я не уверен, есть ли другой метод, кроме использования статических ресурсов .

0 голосов
/ 04 февраля 2011

На самом деле это ожидаемое поведение: DataContex t для DataGridCell - это полная строка.

, поэтому у вас есть 3 решения: либо вы добавляете привязку в код, например:

в конструкторе каждого столбца:

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

(вам нужно найти способ получить "thisColumnIndex". Что касается меня, я добавляю столбцы сразу после их создания, так что япросто поместите туда «dataGridOwner.Columns.Count».

или ...

, вы можете найти способ получить нужный DataContext для каждой ячейки (пробовал это, но он плохо испортилсякогда виртуализация столбца / строки включена)

или ...

посмотрите там:

Привязка свойства объекта ячейки к DataGridCell в WPF DataGrid

Лично я считаю, что первый лучше для моих целей (так как я все равно добавляю свои столбцы в коде позади), но в конечном итоге это зависит от вас ...


Что касается columnHeaders (и только columnsHeaders, а не строк), вы могли бы такжеo исследовать способ «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;

и в xaml вашей dataGrid, что-то вроде:

<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" содержит определения для всехздесь указаны свойства.

надеюсь, это поможет.

0 голосов
/ 13 октября 2010

Не знаю, сработает ли это для вашей ситуации, но вы можете попробовать что-то вроде этого: 1) Дайте вашему окну атрибут Name, например Name = ZeWindow.2) Свяжите свой DataGridTextBoxColumn заголовок следующим образом:

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

Таким образом, вместо привязки к DataContext из DataGrid, вы привязываете к DataContext из UIElement с помощьюName = ZeWindow.

PS: я довольно новичок в WPF, так что это может не работать с окном, но я сделал нечто подобное, используя UserControls

...