【问题标题】:WPF Make ComboBox selection trigger multiple properties changeWPF使组合框选择触发多个属性更改
【发布时间】:2018-02-15 07:26:34
【问题描述】:

我有两个具有相同 Name 和 Position 属性的类。 DataGrid 中的 ComboBox 具有从数据库中获取的 StaffMember 类的列表。它仅显示名称,但在选择时,Name 和 Position 属性应在绑定到另一个类的 ObservableCollection 的 DataGrid 中更改 - Person。

到目前为止,我使用组合框的 SelectionChanged 事件来浏览 VisualTree,访问父 DataContext 并一次更改两个属性。

有什么不同的方法吗?

更新。这是一张说明图:

我从第三方服务获取名称和职位,并在组合框中显示名称。当用户选择一个名称时,UI 应该更新表中的 Name 和 Position 属性。该表还具有现实世界中的年龄和许多其他列/属性。这就是为什么有两个类:从数据库中选择的名称/职位列表和作为表的 ItemSource 的类。我还必须处理人们同名但职位不同的情况。希望这能更好地解释这个问题。

 public class StaffMember : NotifyObject
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged("Name"); }
        }

        private string _position;
        public string Position
        {
            get { return _position; }
            set { _position = value; OnPropertyChanged("Position"); }
        }

    }

    public class Person : NotifyObject
    {
        private string _name;
        public string Name
        {
            get { return _name; }
            set { _name = value; OnPropertyChanged("Name"); }
        }

        private string _position;
        public string Position
        {
            get { return _position; }
            set { _position = value; OnPropertyChanged("Position"); }
        }

        public double Age { get; set; }
    }

视图模型:

    public class ViewModel : NotifyObject
    {
        public ObservableCollection<Person> SelectedPeople { get; set; }
        public List<StaffMember> Staff { get; set; }

        public ViewModel()
        {
            Staff = new List<StaffMember>
            {
                new StaffMember { Name = "Sigmund Freud", Position = "Psychologist"},
                new StaffMember { Name = "Louis Armstrong", Position = "Musician"},
                new StaffMember { Name = "John Doe", Position = "Superviser"},
                new StaffMember { Name = "John Doe", Position = "Manager"},
            };

            SelectedPeople = new ObservableCollection<Person> {
                new Person { Name = "Sigmund Freud", Position = "123", Age= 161 },
                new Person(),
                new Person() };
        }
    }

    public abstract class NotifyObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;

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

        public void RaiseProperychanged(string propertyName)
        {
            OnPropertyChanged(propertyName);
        }
    }

XAML:

<Grid>
        <DataGrid ItemsSource="{Binding SelectedPeople}"
                  AutoGenerateColumns="False"
                  CanUserAddRows="False">
            <DataGrid.Columns>
                <DataGridTemplateColumn Header="Name">
                    <DataGridTemplateColumn.CellTemplate>
                        <DataTemplate>
                            <ComboBox x:Name="ComboBoxSelect" ItemsSource="{Binding ElementName=TheMainWindow, Path=DataContext.Staff}"
                                      SelectedValue="{Binding RelativeSource={RelativeSource Mode=FindAncestor, AncestorType=DataGridRow}, Path=DataContext.Name, Mode=TwoWay}"
                                      DisplayMemberPath="Name"
                                      SelectedValuePath="Name"
                                      SelectionChanged="ComboBoxSelect_SelectionChanged"/>
                        </DataTemplate>
                    </DataGridTemplateColumn.CellTemplate>
                </DataGridTemplateColumn>
                <DataGridTextColumn Header="Position" Binding="{Binding Position, Mode=TwoWay}"/>
                <DataGridTextColumn Header="Age" Binding="{Binding Age}"/>
            </DataGrid.Columns>
        </DataGrid>
    </Grid>

代码隐藏:

 private void ComboBoxSelect_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            var comboBox = sender as ComboBox;
            var parent = sender as DependencyObject;
            while (!(parent is DataGridCell))
            {
                parent = VisualTreeHelper.GetParent(parent);
                if (parent is null) return;
            }
            var cell = parent as DataGridCell;
            if (cell == null) return;
            var person = cell.DataContext as Person;
            if (person == null) return;
            person.Position = ((StaffMember)comboBox.SelectedItem).Position.ToString();
        }

【问题讨论】:

  • 只有我不明白 OP 想要达到什么目标吗?
  • 您的视图模型应该有一个 SelectedPerson 属性,ComboBox 的 SelectedItem 属性绑定到该属性。然后你的TextBox 的名字和位置就绑定到SelectedPerson.Name 和SelectedPerson.Position。您永远不必接触代码隐藏。
  • 如果您唯一的问题是是否有不同的方法来解决它,那么这太宽泛了。您要求进行代码审查。有another site。
  • 我知道你想要一个级联组合框:stackoverflow.com/questions/42871459/…

标签: c# wpf combobox datagrid


【解决方案1】:

混合使用 MVVM 和代码隐藏并不是一个好主意。 您在 Person 和 StaffMember 类中有重复的数据。

在 Person 类中拥有 StaffMember 属性怎么样?

public class StaffMember : NotifyObject
{
    private string _name;
    public string Name
    {
        get { return _name; }
        set { _name = value; OnPropertyChanged("Name"); }
    }

    private string _position;
    public string Position
    {
        get { return _position; }
        set { _position = value; OnPropertyChanged("Position"); }
    }

}

public class Person : NotifyObject
{
    private string _staffMember;
    public string StaffMember
    {
        get { return _staffMember; }
        set { _staffMember = value; OnPropertyChanged("StaffMember"); }
    }

    public double Age { get; set; }
}

【讨论】:

  • @sTrenat 更新
  • 让StaffMember 继承自Person 可能是更好的选择,具体取决于其他业务功能。
  • 这是另一种选择。这取决于业务逻辑。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-11-24
  • 2018-06-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多