【问题标题】:How to set SelectedvaluePath in combobox when the itemsource is a Collection of objects?当itemsource是对象集合时,如何在组合框中设置SelectedvaluePath?
【发布时间】:2016-09-18 16:49:15
【问题描述】:

我在 WPF 的 Datagrid 中有一个 Combobox,我的 DataSource 到 Datagrid 是一个类的 Observable 集合。该类包含另一个包含各种属性的类的列表。

这就是我的 Observable Collections 的样子

public ObservableCollection<TimeLog> Logs
    {
        get
        {
            return _logs;
        }
        set
        {
            _logs = value;
        }
    }

这是 Observable Collection 后面使用的类

public class TimeLog
    {
        private List<Projects> _project;
        public List<Projects> Project
        {
            get
            {
                return _project;
            }
            set
            {
                _project = value;
            }
        }

        private string _taskName;
        public string TaskName
        {
            get
            {
                return _taskName;
            }
            set
            {
                _taskName = value;
            }
        }

        private DateTime _dateSelected;
        public DateTime DateSelected
        {
            get
            {
                return _dateSelected;
            }
            set
            {
                _dateSelected = value;
            }
        }

        private double _hoursSpent;
        public double HoursSpent
        {
            get
            {
                return _hoursSpent;
            }
            set
            {
                _hoursSpent = value;
            }
        }

        /// <summary>
        /// Empty Constructor
        /// </summary>
        public TimeLog()
        {
            _project = new List<Projects>() { new Projects() };
            _dateSelected = DateTime.Today;
            _taskName = string.Empty;
            _hoursSpent = 0.0;
        }
    }

这是我的项目类..

    public class Projects
    {
       private string _projectName;

       public string ProjectName
       {
          get
          {
             return _projectName;
          }
          set
          {
              _projectName = value;
          }
       }

      private DateTime _startDate;
      public DateTime Startdate
      {
        get
        {
            return _startDate;
        }
        set
        {
            _startDate = value;
        }
      }


      private DateTime _enddate;
      public DateTime EndDate
      {
        get
        {
            return _enddate;
        }
        set
        {
            _enddate = value;
        }
      }

      /// <summary>
      /// Could be optional property. But useful for efficient time logging
      /// </summary>
      private double _percentageAllocation;
      public double PercentageAllocation
      {
        get
        {
            return _percentageAllocation;
        }
        set
        {
            _percentageAllocation = value;
        }
      }

      public Projects()
      {
        _projectName = string.Empty;
        _startDate = DateTime.Today;
        _enddate = DateTime.Today;
        _percentageAllocation = 0.0;
      }
}

这就是我的 XAML 的样子。

 <DataGrid  ItemsSource="{Binding Logs}" AutoGenerateColumns="False" CanUserAddRows="False">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Project Name">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox Name="cbProjects" ItemsSource="{Binding Project}" SelectedItem="{Binding DataContext.ComboSelectedItem,Converter={StaticResource covert},UpdateSourceTrigger=PropertyChanged}" >
                            </ComboBox>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTemplateColumn Header="Allocation">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <TextBlock Name="tbAllocation" Text="{Binding DataContext.ComboSelectedItem,Converter={StaticResource covert},UpdateSourceTrigger=PropertyChanged}"></TextBlock>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Binding="{Binding TaskName}" Header="Task Name"></DataGridTextColumn>
                <DataGridTextColumn Binding="{Binding HoursSpent}" Header="Hours Spent"></DataGridTextColumn>
            </DataGrid.Columns>
        </DataGrid>

放置在数据网格内的 Combobox 需要通过 SelectedvaluePath 属性绑定到 Projects 类的 AllocationPercentage 属性。我已经尝试了很多次,但运气不佳。有人可以指导在这些情况下需要做什么,如果我在这个实现中做错了什么,请纠正我。

我需要完成的是,每当我选择 Combobox 的值时(因为 Combobox 是 Projects 类型),我需要在下面的文本块中绑定该选定的值(最好是 AllocationPercentage)。强>

【问题讨论】:

  • 很难看出这里实际发生了什么。 DataContext.ComboSelectedItem 来自哪里,您的 covert 转换器是什么样的?
  • 数据网格的父级的数据上下文是什么?您定义了ItemsSource="{Binding Logs}",但我们不知道数据上下文是什么。确保有分配给页面或数据网格的数据上下文(在 wpf 或代码隐藏中),例如 &lt;DataGrid DataContext="{Binding Logs}" ItemsSource="{Binding}" ... &gt;
  • 选定的值路径是一个字符串。只需给它属性的名称。
  • @RobbieVercammen 我在末尾添加了一个段落来描述我期望发生的事情。您能提供更多帮助吗?
  • @RobbieVercammen 我放置的转换器只是为了调试。并且 Datacontext 是指窗口的数据上下文。

标签: c# wpf xaml combobox datagrid


【解决方案1】:

您希望您的网格在值更改时更新,但您尚未实现INotifyPropertyChanged 接口。您有一个 ObservableCollection 但您的 TimeLog 类没有可观察的属性。

public class TimeLog : INotifyPropertyChanged
{
    public event PropertyChangedEventHandler PropertyChanged;

    // extra property for the selected project
    private Projects _selectedProjects 
    public Projects SelectedProjects
    {
        get 
        {
            if (_selectedProjects == null && _project.Any())
            {
                _selectedProjects = _project.First();
            }
            return _selectedProjects;
        };
        set
        {
             _selectedProjects = value;
             OnPropertyChanged("_SelectedProjects");
        };
    }
    List<Projects> _project;

    // Ommited the rest

    protected void OnPropertyChanged(string name)
    {
        PropertyChangedEventHandler handler = PropertyChanged;
        if (handler != null)
        {
            handler(this, new PropertyChangedEventArgs(name));
        }
    }
}

因为这是我的首选方式,您可以像这样重新排列您的 WPF:

            <DataGridTemplateColumn Header="Project Name">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <ComboBox Name="cbProjects" DataContext="{Binding}" ItemsSource="{Binding Project}" SelectedItem="{Binding Projects}" SelectionChanged="OnMyComboBoxChanged" >
                        </ComboBox>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>
            <DataGridTemplateColumn Header="Allocation">
                <DataGridTemplateColumn.CellTemplate>
                    <DataTemplate>
                        <TextBlock Name="tbAllocation" DataContext="{Binding SelectedProjects}" Text="{Binding AllocationPercentage"></TextBlock>
                    </DataTemplate>
                </DataGridTemplateColumn.CellTemplate>
            </DataGridTemplateColumn>

在c#中

private void OnMyComboBoxChanged(object sender, SelectionChangedEventArgs e)
{
    var cbb = (ComboBox)sender;
    var projects= (Projects)cbb.SelectedItem;
    var timeLog = (TimeLog)cbb.DataContext;

    timeLog.SelectedProjects = projects;
}

我认为这就是你想要去的方向。 这是我从头顶写的,对任何编译错误深表歉意:)

【讨论】:

  • 谢谢。一旦我实施了建议的更改,我会通知您
  • 解决了我的问题。
  • 很高兴我能帮上忙 :)
猜你喜欢
  • 1970-01-01
  • 2016-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2015-11-18
  • 2017-11-22
  • 2019-06-24
  • 1970-01-01
相关资源
最近更新 更多