2016-12-28 1 views
1

Je tente de créer un contrôle DataGrid pour gérer une grille de propriétés. J'ai une classe abstraite pour ma classe de base de paramètres que les paramètres de différents types implémentent. Cette classe de base contient des variables qui sont partagées entre chaque paramètre (comme Group, Name, IsLocked, etc.), puis chaque paramètre gère les informations pertinentes pour le type particulier. Par exemple, un paramètre de nombre peut utiliser un curseur pour le contrôle utilisateur, qui utilise également des valeurs min/max, etc.Problème de liaison de données WPF: UserControls dans DataGrid Les cellules ne sont pas liées

J'ai créé une classe qui est une collection observable de mon paramètre de base, et l'a établie comme une ressource statique pour un CollectionViewSource:

<UserControl.Resources> 
    <local:Parameters x:Key="Parameters"/> 
    <CollectionViewSource x:Key="cvsParameters" Source="{StaticResource Parameters}" /> 
</UserControl.Resources> 

Puis dans mon DataGrid, j'utilise le style déclenche pour basculer entre les commandes utilisateur pour chacun de mes paramètres:

<DataGrid x:Name="DataGrid_Globals" 
      ItemsSource="{Binding Source={StaticResource cvsParameters}}" 
      AutoGenerateColumns="False" 
      CanUserAddRows="False"> 
    <DataGrid.Columns> 
     <DataGridTextColumn Header="Key" Binding="{Binding Key}" IsReadOnly="True"/> 
     <DataGridTemplateColumn Width="*" > 
      <DataGridTemplateColumn.CellTemplate> 
       <DataTemplate> 
        <ContentControl> 
         <ContentControl.Style> 
          <Style TargetType="ContentControl"> 
           <Style.Triggers> 
            <DataTrigger Binding="{Binding UIType}" Value="Text"> 
             <Setter Property="ContentTemplate"> 
              <Setter.Value> 
               <DataTemplate> 
                <controls:ucText DataContext="{Binding}"/> 
               </DataTemplate> 
              </Setter.Value> 
             </Setter> 
            </DataTrigger> 
            <DataTrigger Binding="{Binding UIType}" Value="Number"> 
             <Setter Property="ContentTemplate"> 
              <Setter.Value> 
               <DataTemplate> 
                <controls:ucNumber DataContext="{Binding}"/> 
               </DataTemplate> 
              </Setter.Value> 
             </Setter> 
            </DataTrigger> 
           </Style.Triggers> 
          </Style> 
         </ContentControl.Style> 
        </ContentControl> 
       </DataTemplate> 
      </DataGridTemplateColumn.CellTemplate> 
     </DataGridTemplateColumn> 
    </DataGrid.Columns> 
</DataGrid> 

Mes contrôles utilisateur sont mis en place avec leur contexte de données déclaré en XAML:

<UserControl.DataContext> 
    <local:TestNumber_cls/> 
</UserControl.DataContext> 
<Grid HorizontalAlignment="Stretch"> 
    <Slider 
     Value="{Binding NumberValue}" 
     Minimum="{Binding Min}" 
     Maximum="{Binding Max}" 
     /> 
</Grid> 

Je n'arrive pas à comprendre comment m'assurer que mes commandes utilisateur se lient correctement. Mon autre colonne fonctionne bien, avec chaque valeur Key apparaissant, étant correctement liée et mise à jour (pour cet exemple, c'est juste la colonne "Key", mais tous les champs de la classe de base se comportent très bien.) Les UserControls corrects sont également sélectionnés sur l'UIType DataTrigger, mais les UserControls instancient simplement à partir d'un constructeur vide et ne lient pas.

J'ai également confirmé que les instances autonomes de mes UserControls fonctionnent correctement et se lient correctement. Pour, par exemple, cela fonctionne quand je mis le datacontext de code derrière (que je ne veux pas faire):

this.OneOffNumberUserControl.DataContext = ((Parameters)this.ParameterGrid.Resources["Parameters"])[2]; 

J'ai aussi essayé d'enlever le DataContext = « {Binding} » de mes contrôles utilisateur , mais cela ne change rien.

Répondre

0

Si vous voulez mettre des contrôles différents pour les sous-classes différentes, spécifier différents DataTemplates, puis

<!-- subtype-specific column --> 
          <DataGridTemplateColumn Header=""> 
           <DataGridTemplateColumn.CellTemplate> 
            <DataTemplate> 
             <ContentPresenter Content="{Binding}" /> 
            </DataTemplate> 
           </DataGridTemplateColumn.CellTemplate> 
          </DataGridTemplateColumn> 
+0

Cela a beaucoup simplifié mon XAML (merci!), cependant j'obtiens le même comportement à l'exécution, en ce que la commande usercontrol correcte apparaît dans mon DataGrid, mais son DataContext n'est pas lié. – davestasiuk

+0

J'ai trouvé une solution en implémentant un DependencyProperty pour chacun de mes UserControls de sous-classe. Voir la réponse ci-dessous. – davestasiuk

1

En collaboration avec la suggestion de mécanicien ci-dessus, ce qui a grandement simplifié la XAML pour mon réseau immobilier, par le biais d'autres recherches que je aussi appris que j'avais besoin d'implémenter un DependencyProperty pour chaque usercontrol dépendant de la sous-classe. Où j'ai défini le DataTemplate pour chaque DataType dans ma grille de propriétés UserControl, j'ai défini la liaison à mon DependencyProperty.

<UserControl.Resources> 
 
    <local:Parameters x:Key="Parameters"/> 
 
    <CollectionViewSource x:Key="cvsParameters" Source="{StaticResource Parameters}" /> 
 
    <DataTemplate DataType="{x:Type local:TestText_cls}"> 
 
     <controls:ucText TextObject="{Binding}"/> 
 
    </DataTemplate> 
 
    <DataTemplate DataType="{x:Type local:TestNumber_cls}"> 
 
     <controls:ucNumber NumberObject="{Binding}"/> 
 
    </DataTemplate> 
 
</UserControl.Resources> 
 
<Grid> 
 
    <DataGrid x:Name="DataGrid_Globals" 
 
       ItemsSource="{Binding Source={StaticResource cvsParameters}}" 
 
       AutoGenerateColumns="False" 
 
       CanUserAddRows="False"> 
 
     <DataGrid.Columns> 
 
      <DataGridTextColumn Header="Key" Binding="{Binding Key}" IsReadOnly="True"/> 
 
      <DataGridTemplateColumn Width="*" > 
 
       <DataGridTemplateColumn.CellTemplate> 
 
        <DataTemplate> 
 
         <ContentPresenter Content="{Binding}"/> 
 
        </DataTemplate> 
 
       </DataGridTemplateColumn.CellTemplate> 
 
      </DataGridTemplateColumn> 
 
     </DataGrid.Columns> 
 
    </DataGrid> 
 
</Grid>

Puis dans le code derrière mes UserControls, je mets en œuvre DependencyProperty:

public static readonly DependencyProperty TextObjectProperty = 
    DependencyProperty.Register("TextObject", 
     typeof(TestText_cls), 
     typeof(ucText), 
     new PropertyMetadata(new TestText_cls())); 

[Bindable(true)] 
public TestText_cls TextObject 
{ 
    get { return (TestText_cls)this.GetValue(TextObjectProperty); } 
    set { this.SetValue(TextObjectProperty, value); } 
} 

public ucText() 
{ 
    InitializeComponent(); 
} 

Enfin, au sein de chaque UserControl, j'assure que je lui ai donné un nom, et puis définissez ma liaison à la variable correcte dans mon DependencyProperty:

<UserControl x:Class="Testing.ucText" 
 
      xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
 
      xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
 
      xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
 
      xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
 
      xmlns:local="clr-namespace:Testing.Classes" 
 
      mc:Ignorable="d" 
 
      d:DesignHeight="300" d:DesignWidth="300" 
 
      Name="TextUI"> 
 
    <Grid HorizontalAlignment="Stretch"> 
 
     <TextBox Text="{Binding ElementName=TextUI, Path=TextObject.Value}"/> 
 
    </Grid> 
 
</UserControl>

J'espère que cela aide quelqu'un d'autre!