2008-11-17 8 views
3

Celui-ci a me beat;Utilisation d'une boîte à outils WPF DatePicker en tant que paramètre d'un ObjectDataProvider utilisé en tant que source d'éléments

J'ai une fenêtre WPF avec deux contrôles (importants pour ce cas), tous deux provenant de la boîte à outils WPF disponible sur CodePlex; Un DatePicker et un DataGrid.

Le DataContext de cette fenêtre est défini sur un objet CLR qui contient toutes les informations dont il a besoin. Cet objet CLR a une grande liste de données et une méthode appelée GetDataForDate (DateTime date) qui détermine la date à laquelle nous verrons les données.

Comment puis-je créer un objet ObjectDataProvider (que je suppose être la solution correcte) que le DataGrid peut lier, qui donne accès aux données retournées par GetDataForDate() appelé avec la date sélectionnée de DatePicker comme paramètre? En d'autres termes, je souhaite que l'utilisateur utilise la datepicker pour choisir une date et que la grille se mette automatiquement à jour chaque fois que la date est modifiée pour refléter les données correctes.

Quel genre de magie noire dois-je faire pour réaliser quelque chose comme ceci - ce que je devine devrait être un scénario de liaison de données relativement commun?

Merci d'avance!

Répondre

6

Voici mon code complet. J'espère que cela aidera.

Le code XAML:

<Window x:Class="DataGridSort.Window1" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:dg="clr-namespace:Microsoft.Windows.Controls;assembly=WPFToolkit" 
    xmlns:System="clr-namespace:System;assembly=mscorlib" 
    Title="Window1" Height="413" Width="727" 
     x:Name="_this"> 
    <Window.Resources> 
     <ObjectDataProvider ObjectInstance="_this.DataContext" 
          MethodName="GetFromDate" 
          x:Key="odp"> 
      <ObjectDataProvider.MethodParameters> 
       <System:DateTime>2008-01-01</System:DateTime> 
      </ObjectDataProvider.MethodParameters> 
     </ObjectDataProvider> 
    </Window.Resources> 
    <Grid> 
     <Grid.RowDefinitions> 
      <RowDefinition Height="Auto"/> 
      <RowDefinition Height="*"/> 
     </Grid.RowDefinitions> 

     <dg:DatePicker Grid.Row="0" x:Name="dtpSource" > 
      <dg:DatePicker.SelectedDate> 
       <Binding Source="{StaticResource odp}" 
         Path="MethodParameters[0]" 
          BindsDirectlyToSource="True" 
          Mode="OneWayToSource"/> 
      </dg:DatePicker.SelectedDate> 
     </dg:DatePicker> 

     <dg:DataGrid x:Name="dtgGrid" 
          ItemsSource="{Binding Source={StaticResource odp}}" 
          AutoGenerateColumns="True" 
          Grid.Row="1"/> 
    </Grid> 
</Window> 

Le code derrière:

public partial class Window1 : Window 
{ 
    public Window1() 
    { 
     InitializeComponent(); 

     LoadData(); 
    } 

    protected void LoadData() 
    { 
     DataContext = new Data(); 
     ObjectDataProvider odp = this.Resources["odp"] as ObjectDataProvider; 

     odp.ObjectInstance = DataContext; 
    } 
} 

et l'objet métier:

public class DataItem 
{ 
    public string Name { get; set; } 
    public int BirthYear { get; set; } 
} 

public class Data 
{ 
    private readonly List<DataItem> data; 

    public Data() 
    { 
     data = new List<DataItem>(); 
     data.Add(new DataItem { Name = "John", BirthYear = 2007 }); 
     data.Add(new DataItem { Name = "Mike", BirthYear = 2007 }); 
     data.Add(new DataItem { Name = "Aaron", BirthYear = 2006 }); 
     data.Add(new DataItem { Name = "Bill", BirthYear = 2006 }); 
     data.Add(new DataItem { Name = "Steven", BirthYear = 2005 }); 
     data.Add(new DataItem { Name = "George", BirthYear = 2004 }); 
     data.Add(new DataItem { Name = "Britany", BirthYear = 2004 }); 
    } 

    public List<DataItem> GetFromDate(DateTime dt) 
    { 
     return this.data.Where(d => d.BirthYear == dt.Year).ToList(); 
    } 
} 
+0

Puis-je épouser votre cerveau? Cela a fonctionné - la différence par rapport à l'endroit où j'étais était essentiellement que je n'ai pas essayé de définir l'ObjectInstance à l'aide du code. Merci beaucoup pour l'aide! –

+0

Si je ne veux pas montrer toutes les données, que dois-je faire? Par exemple, dans ce cas, je veux juste voir le col "Nom", ne veut pas voir le col "Année". J'ai essayé d'ajouter les noms à une liste de chaîne et de retourner la liste, mais ce que je vois est un col avec "Longueur" et je ne sais pas d'où vient la "Longueur"! – yeeen

1

Vous pouvez configurer une liaison OneWayToSource sur la propriété DatePicker.SelectedDate qui pousse la valeur de texte dans ObjectDataProvider MethodParameter.

mis en chantier par la création du ObjectDataProvider:

<ObjectDataProvider ObjectType="{x:Type theObjectType}" 
         MethodName="GetDataForDate" 
         x:Key="odp"> 
     <ObjectDataProvider.MethodParameters> 
      <System:DateTime>2008-01-01</System:DateTime> 
     </ObjectDataProvider.MethodParameters> 
    </ObjectDataProvider> 

lient ensuite la propriété SelectedDate du DatePicker au ObjectDataProvider:

<dg:DatePicker x:Name="datePicker" > 
    <dg:DatePicker.SelectedDate> 
     <Binding Source="{StaticResource odp}" 
       Path="MethodParameters[0]" 
        BindsDirectlyToSource="True" 
        Mode="OneWayToSource"/> 
    </dg:DatePicker.SelectedDate> 
</dg:DatePicker> 

Et lient enfin le ObjectDataProvider à votre ObjectDataProvider:

<dg:DataGrid x:Name="dtgGrid" 
      ItemsSource="{Binding Source={StaticResource odp}}" 
      AutoGenerateColumns="False"/> 
+0

Wow, c'était .. Non-évident ..;) Merci, je pense que je comprends l'essentiel. Cependant, je reçois une pile d'exceptions, il essaie d'instancier un objet du type spécifié - comment puis-je lui demander d'utiliser l'objet non statique représenté par mon DataContext? –

+0

Supprime la propriété ObjectType du code XAML et affecte DataContext à ObjectInstance. Vous devez donner un nom à votre fenêtre. Puis: ... – sacha

0

Si vous construisez votre classe avec INotifyPropertyChanged comme ceci:

public class MyDataObject : INotifyPropertyChanged 
{ 
    private DateTime _SelectedDate; 
    public DateTime SelectedDate 
    { 
     get 
     { 
      return _SelectedDate; 
     } 
     set 
     { 
      _SelectedDate = value; 
      NotifyPropertyChanged("SelectedDate"); 
      GetDataForDate(); 
     } 
    } 

    private ObservableCollection<YourDataType> _Data; 
    public ObservableCollection<YourDataType> Data 
    { 
     get 
     { 
      return _Data; 
     } 
     set 
     { 
      _Data = value; 
      NotifyPropertyChanged("Data"); 
     } 
    } 

    public void GetDataForDate() 
    { 
     // Your code here to fill the Data object with your data 
    } 


    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged; 

    private void NotifyPropertyChanged(string propertyName) 
    { 
     if (this.PropertyChanged != null) 
      this.PropertyChanged(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    #endregion 
} 

Ensuite, vous pouvez créer votre ObjectDataProvider en XAML et vous lier directement à celui-ci. Dans vos ressources:

<ObjectDataProvider x:Key="MyDataSource" ObjectType="{x:Type local:MyDataObject}" /> 

et se lient alors:

<DockPanel> 
    <toolkit:DatePicker SelectedDate="{Binding Path=SelectedDate, Mode=Default, Source={StaticResource MyDataSource}}"/> 
    <toolkit:DataGrid ItemsSource="{Binding Path=Data, Mode=Default, Source={StaticResource MyDataSource}}"/> 
</DockPanel> 
1

Une chose que nous devrions prendre en compte est que la propriété SelectedDate du DatePicker retourne un DateTime nullable (ce qui signifie: DateTime au lieu de simplement DateTime). La raison pour laquelle j'ai soulevé cette question est parce que si votre signature de méthode contient un simple DateTime, WPF retournera une erreur comme indiqué par Rune Jacobsen, parce qu'il ne peut pas trouver la bonne signature de méthode.

HTH! Bon article BTW

Questions connexes