使用MVVM在WPF中将集合数据绑定到ComboBox的正确方法?

时间:2016-02-04 08:58:24

标签: wpf data-binding

我正在使用 MVVM 模式,开发我的 WPF 应用程序。我还使用 Entity Framework 作为ORM。这是我的模型( EF ):

public class User : BaseEntity
{
    public string Name { get; set; }

    public int OfficeId { get; set; }
    public Office Office { get; set; }
}

public class Office : BaseEntity
{
    public string Name { get; set; }

    public int DepartmentId { get; set; }
    public Department Department { get; set; }

    public virtual ICollection<User> Users { get; set; }
}

public class Department : BaseEntity
{
    public string Name { get; set; }

    public virtual ICollection<Office> Offices { get; set; }
}

我们假设,我的上下文中有一个User类的实例:

   var userInstance = context.Get<User>().Single(user => user.ID == 1);

现在我想将此实例传递给我的View以对具体用户进行一些更改(例如,调用UserEditView),因此我必须创建一个UserModel类来处理根据MVVM的User数据。所以,这就是我认为我必须在我的代码中编写的内容:

public class UserModel : ObservableObject
{
    private User user;

    public string Office Office
    {
        get
        {
            return this.user.Office.Name;
        }
        set
        {
            //what shoud I write Here??
            if(value != user.Office)
            {
                 user.Office=value;
                 OnPropertyChanged("Office");
            }
        }
    }
}

我真的很沮丧!我应该怎么处理?有成千上万的例子,但它们很简单。我想知道我应该怎样做才能在我的EditView中创建一个ComboBox,其中列出了我的数据库中存在的所有办公室。办事处清单应取决于另一个Combobox,其中包含部门清单。

  • 但我应该从哪里获取此列表?
  • 我应该从UserModel传递一个集合吗?或者是什么?
  • 有人可以给我一个关于如何正确执行此操作的简单示例吗?

PS :当然,我知道实现这种行为的几种方法,但在这种情况下,我的代码似乎很丑陋而且无法维护。请帮忙。非常感谢!

1 个答案:

答案 0 :(得分:1)

这取决于您的数据库架构。这是一些常见的建议(但可能还有很多其他建议)。

  1. 不要惊慌 - 你有一个正确的问题。
  2. 创建视图模型,将其设置为窗口的主视图模型。
  3. 在您的视图模型中创建两个集合用户(包含UserModels)和部门(包含DepartmentMode),,因为您每次重新选择部门时都要更改办公室,而不是#39 ; t需要主视图模型中的办公室集合
  4. 从您的数据库中提取每个收集数据。
  5. 使用INPC实现每个模型。
  6. 考虑WPF MVVM最佳实践。
  7. 应用正确的绑定。
  8. 快乐 - 你是一名程序员。
  9. 更新 - 1

    XAML代码

        <Grid x:Name="LayoutRoot">
        <Grid.DataContext>
            <someBindingExampleSoHelpAttempt:MainViewModel/>
        </Grid.DataContext>
        <ListView ItemsSource="{Binding Users}">
            <ListView.ItemContainerStyle>
                <Style TargetType="ListViewItem">
                    <Setter Property="ContentTemplate">
                        <Setter.Value>
                            <DataTemplate DataType="someBindingExampleSoHelpAttempt:UserModel">
                                <Grid>
                                    <Grid.ColumnDefinitions>
                                        <ColumnDefinition Width="100"></ColumnDefinition>
                                        <ColumnDefinition Width="200"></ColumnDefinition>
                                        <ColumnDefinition Width="50"></ColumnDefinition>
                                        <ColumnDefinition Width="50"></ColumnDefinition>
                                    </Grid.ColumnDefinitions>
                                    <TextBox Grid.Column="0" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  Text="{Binding Name, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"/>
                                    <TextBox Grid.Column="1" HorizontalAlignment="Stretch" VerticalAlignment="Stretch"  Text="{Binding LastName, UpdateSourceTrigger=LostFocus, Mode=TwoWay}"/>
                                    <ComboBox Grid.Column="2"
                                              IsTextSearchEnabled="True"     
                                              IsTextSearchCaseSensitive="False"     
                                              StaysOpenOnEdit="True"    
                                              TextSearch.TextPath="DepartmentName"
                                              ItemsSource="{Binding RelativeSource={RelativeSource Mode=FindAncestor, 
                                        AncestorType={x:Type ListView}}, Path=DataContext.Departments}"    
                                              SelectedValue="{Binding Department}"     
                                              DisplayMemberPath="DepartmentName" 
                                              IsEditable="True"
                                              HorizontalAlignment="Stretch"     
                                              VerticalAlignment="Stretch"/>
                                    <ComboBox Grid.Column="3"
                                              IsTextSearchEnabled="True"     
                                              IsTextSearchCaseSensitive="False"     
                                              StaysOpenOnEdit="True"
                                              IsEditable="True"
                                              TextSearch.TextPath="OfficeName"
                                              ItemsSource="{Binding OfficesCollection}"    
                                              SelectedValue="{Binding Office}"     
                                              DisplayMemberPath="OfficeName"      
                                              HorizontalAlignment="Stretch"     
                                              VerticalAlignment="Stretch"/>
                                </Grid>
    
                            </DataTemplate>
                        </Setter.Value>
                    </Setter>
                </Style>
            </ListView.ItemContainerStyle>
        </ListView></Grid>
    

    虚拟机和型号

        public class MainViewModel:BaseObservableObject
    {
        private DepartmentModel _selectedDepartment;
        private OfficeModel _selectedOffice;
    
        public MainViewModel()
        {
            Dal = new DataLayer();
            Users = new ObservableCollection<UserModel>();
            Departments = new ObservableCollection<DepartmentModel>(Dal.GetAllDepartments());
            InitUsersCollection();
        }
    
        private void InitUsersCollection()
        {
            if(Departments == null) return;
            Departments.ToList().ForEach(model =>
            {
                model.Offices.ToList().ForEach(officeModel =>
                {
                    if (officeModel.Users == null) return;
                    officeModel.Users.ToList().ForEach(userModel => Users.Add(userModel));
                });
            });
        }
    
        public ObservableCollection<UserModel> Users { get; set; }
    
        public ObservableCollection<DepartmentModel> Departments { get; set; }
    
        private DataLayer Dal { get; set; }
    
    }
    
    public class DataLayer
    {
        public List<DepartmentModel> GetAllDepartments()
        {
            //pull and map your using your DB service
            //For example:
            return new List<DepartmentModel>
            {
                new DepartmentModel
                {
                    DepartmentId = 1,
                    DepartmentName = "A",
                    Offices = new ObservableCollection<OfficeModel>
                    {
                        new OfficeModel
                        {
                            DepartmentId = 1,
                            OfficeName = "AA",
                            Users = new ObservableCollection<UserModel>(new List<UserModel>
                            {
                                new UserModel {Name = "Avicenna", LastName = "Abu Ali Abdulloh Ibn-Sino"},
                                new UserModel {Name = "Omar", LastName = "Khayyam"},
                                new UserModel {Name = "RAMBAM", LastName = "Moshe ben Maimon"}
                            })
                        },
                        new OfficeModel 
                        {
    
                            DepartmentId = 1, 
                            OfficeName = "AB", 
                            Users = new ObservableCollection<UserModel>(new List<UserModel>
                            {
                                new UserModel {Name = "Leo", LastName = "Tolstoi"},
                                new UserModel {Name = "Anton", LastName = "Chekhov"},
                            })},
                    }
                },
                new DepartmentModel
                {
                    DepartmentId = 2,
                    DepartmentName = "B",
                    Offices = new ObservableCollection<OfficeModel>
                    {
                        new OfficeModel
                        {
                            DepartmentId = 2, OfficeName = "BA",
                            Users = new ObservableCollection<UserModel>(new List<UserModel>
                            {
                                new UserModel {Name = "B", LastName = "O"},
                                new UserModel {Name = "B", LastName = "N"},
                            }),
                        },
                        new OfficeModel
                        {
                            DepartmentId = 2, OfficeName = "BB",
                            Users = new ObservableCollection<UserModel>(new List<UserModel>
                            {
                                new UserModel {Name = "John", LastName = "Walker"},
                                new UserModel {Name = "Gregory", LastName = "Rasputin"},
                            }),
                        },
                    }
                },
                new DepartmentModel
                {
                    DepartmentId = 3,
                    DepartmentName = "C",
                    Offices = new ObservableCollection<OfficeModel>
                    {
                        new OfficeModel {DepartmentId = 3, OfficeName = "CA"},
                        new OfficeModel {DepartmentId = 3, OfficeName = "CB"},
                        new OfficeModel {DepartmentId = 3, OfficeName = "CC"}
                    }
                }
            };
        }
    }
    
    public class OfficeModel:BaseObservableObject
    {
        private int _departmentModel;
        private string _officeName;
        private DepartmentModel _department;
        private ObservableCollection<UserModel> _users;
    
        public int DepartmentId
        {
            get { return _departmentModel; }
            set
            {
                _departmentModel = value;
                OnPropertyChanged();
            }
        }
    
        public DepartmentModel Department
        {
            get { return _department; }
            set
            {
                _department = value;
                OnPropertyChanged();
            }
        }
    
        public string OfficeName
        {
            get { return _officeName; }
            set
            {
                _officeName = value;
                OnPropertyChanged();
            }
        }
    
        public ObservableCollection<UserModel> Users
        {
            get { return _users; }
            set
            {
                _users = value;
                OnPropertyChanged(()=>Users);
            }
        }
    }
    
    public class DepartmentModel:BaseObservableObject
    {
    
        private string _departmentName;
    
        public string DepartmentName
        {
            get { return _departmentName; }
            set
            {
                _departmentName = value;
                OnPropertyChanged();
            }
        }
    
        public int DepartmentId { get; set; }
    
        public ObservableCollection<OfficeModel> Offices { get; set; }
    }
    
    public class UserModel:BaseObservableObject
    {
        private string _name;
        private string _lastName;
        private DepartmentModel _department;
        private OfficeModel _office;
    
        public string Name
        {
            get { return _name; }
            set
            {
                _name = value;
                OnPropertyChanged();
            }
        }
    
        public string LastName
        {
            get { return _lastName; }
            set
            {
                _lastName = value;
                OnPropertyChanged();
            }
        }
    
        public DepartmentModel Department
        {
            get { return _department; }
            set
            {
                _department = value;
                OnPropertyChanged();
                OnPropertyChanged(()=>OfficesCollection);
            }
        }
    
        public ObservableCollection<OfficeModel> OfficesCollection
        {
            get { return Department.Offices; }
        }
    
        public OfficeModel Office
        {
            get { return _office; }
            set
            {
                _office = value;
                OnPropertyChanged();
            }
        }
    }
    
    /// <summary>
    /// implements the INotifyPropertyChanged (.net 4.5)
    /// </summary>
    public class BaseObservableObject : INotifyPropertyChanged
    {
        public event PropertyChangedEventHandler PropertyChanged;
    
        protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null)
        {
            var handler = PropertyChanged;
            if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName));
        }
    
        protected virtual void OnPropertyChanged<T>(Expression<Func<T>> raiser)
        {
            var propName = ((MemberExpression)raiser.Body).Member.Name;
            OnPropertyChanged(propName);
        }
    
        protected bool Set<T>(ref T field, T value, [CallerMemberName] string name = null)
        {
            if (!EqualityComparer<T>.Default.Equals(field, value))
            {
                field = value;
                OnPropertyChanged(name);
                return true;
            }
            return false;
        }
    }
    

    但请注意,这只是数百种方法之一。 如果你需要代码示例,这里的SO。 问候。