【问题标题】:Using a WPF toolkit DatePicker as a parameter to an ObjectDataProvider used as an itemssource使用 WPF 工具包 DatePicker 作为 ObjectDataProvider 的参数,用作 itemssource
【发布时间】:2008-11-17 21:45:56
【问题描述】:

这个我打败了;

我有一个 WPF 窗口,其中包含两个(对于这种情况很重要)控件,它们都来自 CodePlex 提供的 WPF 工具包;一个 DatePicker 和一个 DataGrid。

此窗口的 DataContext 设置为一个 CLR 对象,该对象具有所需的所有信息。这个 CLR 对象有一个大的数据列表,以及一个名为 GetDataForDate( DateTime date ) 的方法,它决定我们将看到哪个日期的数据。

如何创建数据网格可以绑定到的 ObjectDataProvider(我认为这将是正确的解决方案),它提供对使用 DatePicker 的选定日期作为参数调用的 GetDataForDate() 返回的数据的访问?

换句话说,我希望用户使用日期选择器来选择日期,并且每当日期更改以反映正确的数据时,网格应自动更新。

我必须做什么样的黑魔法才能实现这样的事情 - 我猜这应该是一个相对常见的数据绑定场景?

提前致谢!

【问题讨论】:

    标签: wpf data-binding


    【解决方案1】:

    这是我的完整代码。我希望这会有所帮助。

    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>
    

    背后的代码:

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

    和业务对象:

    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();
        }
    }
    

    【讨论】:

    • 我可以嫁给你的大脑吗!?那行得通 - 与我所处的位置不同,基本上我没有尝试通过代码设置 ObjectInstance。非常感谢您的帮助!
    • 如果我不想显示所有数据,我应该怎么做?例如,在这种情况下,我只想看到“名称”列,不想看到“年份”列。我尝试将名称添加到字符串列表并返回列表,但我看到的是带有“长度”的列,我不知道“长度”来自哪里!
    【解决方案2】:

    您可以在 DatePicker.SelectedDate 属性上设置 OneWayToSource 绑定,将文本值推送到 ObjectDataProvider MethodParameter。

    首先创建 ObjectDataProvider:

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

    然后将 DatePicker 的 SelectedDate 属性绑定到 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>
    

    最后将 ObjectDataProvider 绑定到您的 ObjectDataProvider:

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

    【讨论】:

    • 哇,那是.. 不明显.. ;) 谢谢,我想我明白了。但是,我遇到了一堆异常,它尝试实例化指定类型的对象 - 我如何要求它使用我的 DataContext 表示的非静态对象?
    • 从 XAML 中删除 ObjectType 属性并将 DataContext 分配给 ObjectInstance。 你应该给你的窗口一个名字。然后:...
    【解决方案3】:

    我们应该注意的一点是,DatePicker 的 SelectedDate 属性返回一个可为空的 DateTime(这意味着:DateTime? 而不仅仅是 DateTime)。 我提出这个问题的原因是因为如果您的方法签名包含简单的 DateTime,WPF 将返回如 Rune Jacobsen 所示的错误,因为它找不到正确的方法签名。

    HTH!好文章顺便说一句

    【讨论】:

      【解决方案4】:

      如果你像这样使用 INotifyPropertyChanged 构建你的类:

      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
      }
      

      然后您可以在 XAML 中创建您的 ObjectDataProvider 并直接绑定到它。在您的资源中:

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

      然后绑定:

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

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2010-12-20
        • 1970-01-01
        • 2021-04-02
        • 1970-01-01
        相关资源
        最近更新 更多