Привязка к DataContext вне текущего контекста ItemsSource
У меня есть 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 ответа
Я уверен, что вы можете сделать то, что вы пытаетесь сделать, используя 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... Я не уверен, есть ли другой метод, кроме использования статических ресурсов.
Это ожидаемое поведение на самом деле: DataContex
т для 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, а не строк), вы можете также изучить способ "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" содержит определения для всех свойств, на которые здесь ссылаются.
надеюсь это поможет.
Не знаю, сработает ли это в вашей ситуации, но вы можете попробовать что-то вроде этого:
1) Дайте вашему окну атрибут Name, например Name=ZeWindow.
2) Свяжите свой DataGridTextBoxColumn
Заголовок как это:
<DataGridTextBoxColumn Header="{Binding Path=DataContext.Tables[Names]/Text, ElementName=ZeWindow}"/>
Так что в основном вместо привязки к DataContext
из DataGrid
привязываешься к DataContext
из UIElement
с именем = ZeWindow.
PS: я довольно новичок в WPF, так что это может не работать с окном, но я сделал нечто подобное, используя UserControls