WPF 多个视图模型和多个用户 Cotnrols

本文关键字:用户 Cotnrols 视图 WPF 模型 | 更新日期: 2023-09-27 18:09:41

所以我有一个页面,其中包含一个使用多个用户控件的 TabTControl(每个用户控件表示 TabItem 的内容(。

我在共享相同 ItemsSource (OrganizationSource( 和 SelectedValue( OrganizationSelected( 属性的两个用户控件中都有一个组合框,

但是,我似乎无法绑定到EventDetails用户控件中的ComboBox,但它在OrganizationDetails用户控件中完美运行。

OutreachMVVM设置为选项卡所在的父页面的数据上下文。我仍然必须为用户控件本身设置数据上下文才能正常工作。

我只需要弄清楚如何在EventDetails内设置组合框的绑定。我看到了一些关于依赖属性的东西,但我不明白。我以为我可以将EventDetails内部组合框的绑定设置为与OrganizationDetails内部组合框的绑定相同,但事实并非如此。

internal class OutreachMVVM : ViewModelBase
{
    public OutreachMVVM()
    {
        EventDetails = new EventDetailsVMB();   
        OrganizationDetails = new OrganizationDetailsVMB();
    }
    public EventDetailsVMB EventDetails { get; set; }
    public OrganizationDetailsVMB OrganizationDetails { get; set; }
}

事件详情VMB:

class EventDetailsVMB : ViewModelBase
{
    private string _eventTypeSelected;
    private string _zipSelected;
    private readonly UserListTableAdapter _userListTableAdapter = new UserListTableAdapter();
    private readonly EventTypeListTableAdapter _eventTypeListTableAdapter = new EventTypeListTableAdapter();
    private readonly CityListTableAdapter _cityListTableAdapter = new CityListTableAdapter();
    private readonly LocationInfoByZipTableAdapter _locationInfoByZipTableAdapter = new LocationInfoByZipTableAdapter();
    public string User { get; set; }
    public string EventName { get; set; }
    public string Location { get; set; }
    public string Address1 { get; set; }
    public string Address2 { get; set; }
    public string City { get; set; }
    public string State { get; set; }
    public string County { get; set; }
    public string ServiceArea { get; set; }
    //Set EventType CombBox
    public ObservableCollection<string> EventTypeSource
    {
        get
        {
            var eventTypeList = _eventTypeListTableAdapter.GetEventTypeList();
            var eventTypeSource = new ObservableCollection<string>();
            eventTypeSource.AddRange(from DataRow row in eventTypeList.Rows select row.ItemArray[0].ToString());
            return eventTypeSource;
        }
    }
    //Set User ComboBox
    public ObservableCollection<string> UserSource
    {
        get
        {
            var userList = _userListTableAdapter.GetUserList();
            var userSource = new ObservableCollection<string>();
            foreach (var username in Enumerable.Where(userList, username => username.Username == Environment.UserName))
            {
                User = username.FullName;
            }
            userSource.AddRange(from DataRow row in userList.Rows select row.ItemArray[0].ToString());
            OnPropertyChanged("User");
            return userSource;
        }
    }
    //Set City RadAutoCompleteBox
    public ObservableCollection<string> CitySource
    {
        get
        {
            var cityList = _cityListTableAdapter.GetCityList();
            var citySource = new ObservableCollection<string>();
            citySource.AddRange(from DataRow row in cityList.Rows select row.ItemArray[0].ToString());
            return citySource;
        }
    } 

    public string EventTypeSelected
    {
        get { return _eventTypeSelected; }
        set
        {
            _eventTypeSelected = value;
            OnPropertyChanged("EventTypeSelected");
        }
    }
    public string ZipSelected 
    { 
        get { return _zipSelected;  }
        set
        {
            _zipSelected = value;
            var locationInfo = _locationInfoByZipTableAdapter.GetLocationInfoByZip(_zipSelected);
            if (locationInfo.Rows.Count != 0)
            {
                City = locationInfo.Rows[0].ItemArray[0].ToString();
                State = locationInfo.Rows[0].ItemArray[1].ToString();
                County = locationInfo.Rows[0].ItemArray[2].ToString();
                ServiceArea = locationInfo.Rows[0].ItemArray[3].ToString();
            }
            else if (ZipSelected.Length == 5) {}
            else
            {
                City = "";
                State = "TX";
                County = null;
                ServiceArea = null;
            }
            OnPropertyChanged("City");
            OnPropertyChanged("State");
            OnPropertyChanged("County");
            OnPropertyChanged("ServiceArea");
        } 
    }
}

组织详细信息VMB:

class OrganizationDetailsVMB : ViewModelBase
{
    private string _organizationName;
    private string _street1;
    private string _street2;
    private string _city;
    private string _state;
    private string _zip;
    private string _county;
    private string _serviceArea;
    private bool _cbo;
    private bool _fbo;
    private bool _mo;
    private bool _sbo;
    private bool _sno;
    private readonly OrganizationListTableAdapter _organizationListTableAdapter = new OrganizationListTableAdapter();
    private readonly OrgByNameTableAdapter _orgByNameTableAdapter = new OrgByNameTableAdapter();
    private readonly OrgTypeByOrgNameTableAdapter _orgTypeByOrgNameTableAdapter = new OrgTypeByOrgNameTableAdapter();
    public string OrganizationSelected
    {
        get { return _organizationName; }
        set
        {
            _organizationName = value;
            var organizationQueryResults = _orgByNameTableAdapter.GetOrganizationByName(_organizationName);
            var orgTypeQueryResults = _orgTypeByOrgNameTableAdapter.GetOrgTypeByName(_organizationName);
            if (organizationQueryResults.Rows.Count != 0)
            {
                OrgStreet1Value = organizationQueryResults.Rows[0].ItemArray[1].ToString();
                OrgStreet2Value = organizationQueryResults.Rows[0].ItemArray[2].ToString();
                OrgCityValue = organizationQueryResults.Rows[0].ItemArray[3].ToString();
                OrgStateValue = organizationQueryResults.Rows[0].ItemArray[4].ToString();
                OrgZipValue = organizationQueryResults.Rows[0].ItemArray[5].ToString();
                OrgCountyValue = organizationQueryResults.Rows[0].ItemArray[6].ToString();
                OrgServiceAreaValue = organizationQueryResults.Rows[0].ItemArray[7].ToString();
                CBO = Convert.ToBoolean(orgTypeQueryResults.Rows[0].ItemArray[1]);
                FBO = Convert.ToBoolean(orgTypeQueryResults.Rows[0].ItemArray[2]);
                SBO = Convert.ToBoolean(orgTypeQueryResults.Rows[0].ItemArray[3]);
                MO = Convert.ToBoolean(orgTypeQueryResults.Rows[0].ItemArray[4]);
                SNO = Convert.ToBoolean(orgTypeQueryResults.Rows[0].ItemArray[5]);
            }
            else
            {
                OrgStreet1Value = "";
                OrgStreet2Value = "";
                OrgCityValue = "";
                OrgStateValue = "";
                OrgZipValue = "";
                OrgCountyValue = "";
                OrgServiceAreaValue = "";
                CBO = false;
                FBO = false;
                SBO = false;
                MO = false;
                SNO = false;
            }
        }
    }
    public ObservableCollection<string> OrganizationSource
    {
        get
        {
            var organizationList = _organizationListTableAdapter.GetOrganizationList();
            var organizationSource = new ObservableCollection<string>();
            organizationSource.AddRange(from DataRow row in organizationList.Rows select row.ItemArray[0].ToString());
            return organizationSource;
        }
    }
    public string OrgStreet1Value
    {
        get { return _street1; }
        set
        {
            if (_street1 != value)
            {
                Validator.ValidateProperty(value,
                    new ValidationContext(this, null, null) { MemberName = "OrgStreet1Value" });
                _street1 = value;
                OnPropertyChanged("OrgStreet1Value");
            }
        }
    }
    public string OrgStreet2Value
    {
        get { return _street2; }
        set
        {
            if (_street2 != value)
            {
                Validator.ValidateProperty(value,
                    new ValidationContext(this, null, null) { MemberName = "OrgStreet2Value" });
                _street2 = value;
                OnPropertyChanged("OrgStreet2Value");
            }
        }
    }
    public string OrgCityValue
    {
        get { return _city; }
        set
        {
            if (_street1 != value)
            {
                Validator.ValidateProperty(value,
                    new ValidationContext(this, null, null) { MemberName = "OrgCityValue" });
                _city = value;
                OnPropertyChanged("OrgCityValue");
            }
        }
    }
    public string OrgStateValue
    {
        get { return _state; }
        set
        {
            if (_state != value)
            {
                Validator.ValidateProperty(value,
                    new ValidationContext(this, null, null) { MemberName = "OrgStateValue" });
                _state = value;
                OnPropertyChanged("OrgStateValue");
            }
        }
    }
    public string OrgZipValue
    {
        get { return _zip; }
        set
        {
            if (_zip != value)
            {
                Validator.ValidateProperty(value,
                    new ValidationContext(this, null, null) { MemberName = "OrgZipValue" });
                _zip = value;
                OnPropertyChanged("OrgZipValue");
            }
        }
    }
    public string OrgCountyValue
    {
        get { return _county; }
        set
        {
            if (_county != value)
            {
                Validator.ValidateProperty(value,
                    new ValidationContext(this, null, null) { MemberName = "OrgCountyValue" });
                _county = value;
                OnPropertyChanged("OrgCountyValue");
            }
        }
    }
    public string OrgServiceAreaValue
    {
        get { return _serviceArea; }
        set
        {
            if (_serviceArea != value)
            {
                Validator.ValidateProperty(value,
                    new ValidationContext(this, null, null) { MemberName = "OrgServiceAreaValue" });
                _serviceArea = value;
                OnPropertyChanged("OrgServiceAreaValue");
            }
        }
    }
    public bool CBO
    {
        get { return _cbo; }
        set
        {
            _cbo = value;
            OnPropertyChanged("CBO");
        }
    }
    public bool FBO
    {
        get { return _fbo; }
        set
        {
            _fbo = value;
            OnPropertyChanged("FBO");
        }
    }
    public bool SBO
    {
        get { return _sbo; }
        set
        {
            _sbo = value;
            OnPropertyChanged("SBO");
        }
    }
    public bool MO
    {
        get { return _mo; }
        set
        {
            _mo = value;
            OnPropertyChanged("MO");
        }
    }
    public bool SNO
    {
        get { return _sno; }
        set
        {
            _sno = value;
            OnPropertyChanged("SNO");
        }
    }
}

"事件详细信息"选项卡:

<TabItem Header="Event Details" x:Name="EventDetailsTab"
            Style="{StaticResource TabStyle}"
            DataContext="{Binding EventDetails}">
    <eventTabs:_1_EventDetailsTab />
</TabItem>

"组织详细信息"选项卡:

<TabItem Header="Organization" x:Name="OrganizationTab"
            Style="{StaticResource TabStyle}"
            DataContext="{Binding OrganizationDetails}">
    <eventTabs:_2_OrganizationTab />
</TabItem>

正如我所说,绑定总体上完美无缺,但我想引用与 OrganizationDetails 关联的绑定,以获取驻留在 EventDetailsTab 和 OrganizationDetailsTab 中的控件。

该项目的代码如下...

<ComboBox Name="OrgNameComboBox" ItemsSource="{Binding OrganizationSource}"
                SelectedValue="{Binding OrganizationSelected,
                                        Mode=TwoWay,
                                        UpdateSourceTrigger=PropertyChanged}" />

WPF 多个视图模型和多个用户 Cotnrols

您将事件详细信息选项卡的 DataContext 设置为 {Binding EventDetails},将组织的 DataContext 选项卡设置为 {Binding OrganizationDetails} ,但组合框绑定到的OrganizationSourceOrganizationSelected字段仅存在于 OrganizationDetailsVMB 类中。一个快速的技巧是更改您的事件详细信息 ComboBox 以指向正确的位置,并将 RelativeSource 绑定回 TabItem 的 DataContext,然后再次向下指向 OrganizationDetails:

<ComboBox Name="OrgNameComboBox" ItemsSource="{Binding OrganizationSource}"
        DataContext="{Binding RelativeSource={RelativeSource AncestorType=TabControl}, Path=DataContext.OrganizationDetails}" 
        SelectedValue="{Binding OrganizationSelected,
        Mode=TwoWay,
        UpdateSourceTrigger=PropertyChanged}" />

老实说,尽管我认为您需要清理您的架构。您的视图模型看起来与基础数据模型而不是视图紧密耦合,以至于您甚至可以在 getter 中访问表适配器,这意味着 A( 您无法进行会话管理,B( 您的视图性能现在将受到 DAL 的限制,您将开始遇到性能问题, C(尝试引入任何类型的多线程将导致ORM中的各种访问冲突。

A(

当您想要跨AppMulti Window拥有一些数据(如组合框信息(时,这种方式很好:

创建 3 个ViewModel(全部继承自 INotifyPropertyChanged 个(。

  1. OrganizationViewModel 包括 OrganizationSourceOrganizationSelected
  2. OrganizationDetailsViewModel 惠特 OrganizationSourceOrganizationSelected
  3. OrganizationEventsViewModel 惠特豪特OrganizationSourceOrganizationSelected

现在,您可以创建一个名为 GeneralData 的简单 Static 类,并在其中创建一个OrganizationViewModel类型的 static 属性,如下所示:

public static class GeneralData{
   public static OrganizationViewModel Organization {get;set;}
}

App.xaml.cs中,用 OrganizationViewModel 的新实例填充 GeneralData 类的 Organization 属性。


还行。。。现在我们有了开始玩所需的一切......

每次你想填充ComboBox你应该使用GeneralData类的Organization[静态属性],如下所示:

<ComboBox Name="OrgNameComboBox"
          DataSource="{Binding Source={x:Static GeneralData.Organization}}"
          ItemsSource="{Binding Source={x:Static GeneralData.Organization.OrganizationSource}}"
          SelectedValue="{Binding Source={x:Static GeneralData.Organization.OrganizationSelected,
                                  Mode=TwoWay, UpdateSourceTrigger=PropertyChanged}" />

每次您想检查在代码隐藏中选择了组合框的哪个项目时(例如在ViewModels内(,您可以轻松地像这样检查它:

var selectedOrganisation = GeneralData.Organization.OrganizationSelected;

注意:我建议您在关闭包含ComboBox的窗口之前运行此代码(以确保没有任何对静态属性的活动引用(:

BindingOperations.ClearAllBindings(OrgNameComboBox);

二(

如果您只有 1 个窗口包含 2 个用户控件,则阻止static属性,而不是上述方式使用以下方式:

创建 3 个ViewModel(全部继承自 INotifyPropertyChanged 个(。

  1. OrganizationViewModel 包括 OrganizationSourceOrganizationSelected
  2. OrganizationDetailsViewModel 惠特豪特OrganizationSourceOrganizationSelected
  3. OrganizationEventsViewModel 惠特豪特OrganizationSourceOrganizationSelected

现在轻松实现此方案:

Window1.xaml.cs

Window1.DataSource= new OrganizationViewModel();

EventUserControl.xaml.cs

EventUserControl.DataSource= new OrganizationEventsViewModel();

OrganizationDetailsUserControl.xaml.cs

EventUserControl.DataSource= new OrganizationDetailsViewModel();

现在在EventUserControlOrganizationDetailsUserControl中创建一个DependencyProperty,以使它们具有ComboBox SelectedItem。您的住宿类型应为 string 。您可以根据本教程创建DependencyProperty基础。例如,在两个UserControl s: SelectedOrganisation中都对DependencyProperty使用此名称

好的,将Combobox放在Window1.xaml中(而不是在任何UserControl内(。现在我们从外部填充这些SelectedOrganisation,如以下代码UserControls

Window1.xaml

<uc.OrganizationDetailsUserControl 
    SelectedOrganisation="{Binding ElementName=OrgNameComboBox, Path=SelectedItem}"/>
<uc.EventUserControl
    SelectedOrganisation="{Binding ElementName=OrgNameComboBox, Path=SelectedItem}"/>

现在,您在UserControl中拥有了ComboBoxSelectedItem,您可以在UserControls中使用它,并使用SelectedOrganisation作为方法参数调用ViewModels的一些方法。

我走的路线是MVVM Light Toolkit。