2010-10-13 31 views
7

J'ai un DataSet lié au Window.DataContext; J'ai aussi un DataGrid:Liaison à DataContext hors du contexte ItemsSource actuel

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

Fondamentalement, je suis en train de lier l'en-tête de cette colonne à DataTable « noms », colonne « Test », première rangée.

Cependant, je ne peux pas le faire correctement. Notez que je peux le lier bien en dehors du DataGrid. ItemsSource de la grille modifie le contexte de données et je ne sais pas comment faire référence à l'extérieur du DataContext d'origine.

Il semble que la liaison réussisse; mais le problème est que l'élément actuel (première rangée) des Tables [Noms] dans le Window.DataContext a été perdu.

Si je mets le DataSet statique et y accède via {x: Static local: dataset} alors tout fonctionne bien. Mais je ne peux pas utiliser les ensembles de données statiques car il y aura plusieurs instances (multi-utilisateurs).

Quelqu'un peut-il me diriger dans la bonne direction?

Répondre

0

Je ne sais pas si cela fonctionnera pour vous, mais vous pouvez essayer quelque chose comme ceci: 1) Donnez à votre fenêtre un attribut de nom, par ex. Nom = ZeWindow. 2) Liez votre DataGridTextBoxColumn tête comme ceci:

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

Donc, fondamentalement, au lieu de se lier au DataContext du DataGrid, vous liez à la DataContext du UIElement avec Name = ZeWindow.

PS: Je suis assez nouveau pour WPF, alors cela pourrait ne pas fonctionner avec la fenêtre, mais je l'ai fait quelque chose de similaire en utilisant UserControls

+0

J'ai également essayé cela. Il donne le même résultat que la méthode FindAncestor dans mon article. C'est à dire: il se lie avec succès, mais le "CurrentItem" du DataContext original a été perdu. Le coupable de mon problème est que j'essaye de me référer à un autre DataTable qui a son propre CurrentItem (ligne [0]); Si je me réfère à une simple propriété alors votre méthode ainsi que le FindAncestor fonctionnerait bien. – vuduy

+0

Ok, je vois, alors je suis désolé mais je ne sais pas quel pourrait être le problème. J'espère que quelqu'un d'autre le saura –

10

Je suis sûr que vous pouvez faire ce que vous essayez de le faire par utilisant la liaison 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> 

J'ai fait un exemple rapide à: http://bitbucket.org/claus/wpf-bindingoutsidedatacontext

Il vous permet de lier à la fenêtre mère, qui dans mon cas a viewmodel comme datacontext (avec la propriété SomethingOutsideDataContext dessus). Vous devez être conscient cependant, ceci ne fonctionnera qu'avec WPF et non Silverlight - le truc 'FindAncestor, AncestorType' n'a pas encore été implémenté dans Silverlight ... Je ne suis pas sûr qu'il y ait une autre méthode, en plus d'utiliser static Ressources.

+0

Si cela ne fonctionne pas pour vous, veuillez ajouter un petit exemple de la structure de l'objet Tables [Items]/Tables [Names] auquel vous essayez de vous lier, et je verrai si je pouvez créer un exemple en utilisant ... – Claus

+0

Assurez-vous également que votre type d'ancêtre est un type de 'Window' et non un type de' UserControl' car la propriété 'DataContext' présentera' null' – Kitson88

0

C'est le comportement attendu en réalité: Le DataContex t pour DataGridCell est le wholeRow.

donc vous avez 3 solutions: soit vous ajoutez votre fixation dans le code derrière comme celui-ci:

dans le constructeur de chaque colonne:

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

(vous devez trouver un moyen d'obtenir le « thisColumnIndex "En ce qui me concerne, j'ajoute les colonnes juste après que je les ai créées, si je mets simplement" dataGridOwner.Columns.Count "là).

ou ...

vous pouvez trouver un moyen d'obtenir le DataContext que vous voulez sur chaque cellule (essayé mais il provoque un plantage du mal quand la virtualisation colonne/ligne est activée)

ou ...

un coup d'oeil là-bas :

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

personnellement, je trouve le premier à être mieux pour mon but (depuis que j'ajouter mes colonnes dans le code derrière de toute façon), mais cela est vraiment à vous à la fin ...


En ce qui ColumnHeaders concerne (et seulement columnsHeaders, pas de lignes), vous pouvez également explorer la manière « DataTemplate »:

définir l'en-tête des colonnes à la colonne elle-même (cette façon, vous définissez la colonne en tant que DataContext pour l'en-tête) et utilisez un DataTemplate.

par exemple:

dans chaque classe de colonne:

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; 

et dans votre XAML de dataGrid, quelque chose comme:

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

bien sûr, ma classe "MyDataGridColumnHeader" contient des définitions pour tous les propriétés référencées ici.

espérons que cela aide.