2 (или более) ComboBox, зависящих друг от друга - PullRequest
4 голосов
/ 09 июня 2010

РЕДАКТИРОВАТЬ: проблема под исправлена, перейдите к редактированию 2 в этом посте.

У меня есть субъект организации и субъект региона. С объектом типа Organization может быть связан один или несколько объектов Region, поэтому у меня есть внешний ключ в моей сущности Region для сущности Organization. Объекты Organization и Region извлекаются из моей базы данных с использованием WCF RIA и структуры сущностей. Я хочу поместить объекты Organization в один ComboBox, а объекты Region - в другой ComboBox, а при выборе организации, имеющей ComboBox для объектов Region, автоматически отображаются только те регионы, которые связаны с выбранной организацией. Должно быть довольно простым, но то, как я его сейчас спроектировал, вообще не работает.

Итак, есть какой-нибудь намек на то, как мне этого добиться? Простой простой пример кода очень ценится! (Я использую SL4, WCF RIA MVVM)

РЕДАКТИРОВАТЬ 2 РЕДАКТИРОВАТЬ 2 РЕДАКТИРОВАТЬ 2 РЕДАКТИРОВАТЬ 2 РЕДАКТИРОВАТЬ 2 РЕДАКТИРОВАТЬ 2:

Используя ответ Venom ElemntBinding, это прекрасно работает сейчас, когда я хочу добавить новый объект в свою коллекцию, и я просто перетаскиваю доступные страны и связанные области, а затем печатаю сайт в текстовом поле ... Я получаю свою комбинацию организации, региона и сайта в моей базе данных:)

Теперь у меня возникла новая проблема, когда я хочу отредактировать сайт в моей коллекции. В режиме РЕДАКТИРОВАНИЯ я хочу, чтобы два выпадающих списка были предварительно выбраны и отключены (BusinessRule заключается в том, что я могу редактировать имя места, а не то, к какой организации или региону он подключен). Поэтому, установив свойство SelectedIndex в выпадающем списке «Организация», я выбираю свою организацию, но при выполнении этого действия в выпадающем списке «Регионы» происходит сбой с ошибкой ссылки на объект.

Ответы [ 2 ]

4 голосов
/ 09 июня 2010

Вы можете достичь этого с помощью некоторых умных ElementBinding с.

Базовый пример:

Допустим, у нас есть простой класс, подобный этому:

public class Country
{
    public string Name { get; set; }

    public IEnumerable<string> Regions { get; set; }
}

Тогда у нас будет два ComboBox: один для выбора страны и другой для выбора региона в этой стране.Второй должен обновляться сам при изменении значения первого.

Хорошо, сначала мы должны сказать Silverlight, как отображать Country.Для сложных сценариев мы могли бы использовать DataTemplate для этого, но сейчас нам понадобится только свойство DisplayMemberPath класса ComboBox.

<ComboBox x:Name="cbCountries" DisplayMemberPath="Name"/>

Итак, мы создаем простую коллекцию этих объектовв коде:

var countries = new List<Country>()
{
    new Country
    {
        Name = "USA",
        Regions = new List<string>
        {
            "Texas", "New York", "Florida", ...
        },
    },
    new Country
    {
        Name = "UK",
        Regions = new List<string>
        {
            "Scotland", "Wales", "England", ...
        },
    },
    ...
};

Я знаю, что это не все регионы в странах-примерах, но это пример Silverlight, а не географический урок.

Теперь мынеобходимо установить ItemsSource из ComboBox для этой коллекции.

cbCountries.ItemsSource = countries;

Оба они могут быть в конструкторе в коде позади.
Хорошо, теперь вернемся к XAML!

Нам понадобится еще один ComboBox и способ сказать ему, чтобы он динамически получал свои предметы из другой коллекции.
Привязка его ItemsSource к другому выбранному элементу ComboBox является наиболее очевидной.способ достижения этого.

<ComboBox x:Name="cbRegion" ItemsSource="{Binding ElementName=cbCountries, Path=SelectedItem.Regions}"/>

Это должно сделать свое дело довольно просто.

Если вы используете MVVM:

Вы можете привязать кItemsSource из первых ComboBox из ViewModel.Остальное остается тем же.
Чтобы определить, какие выбранные значения относятся к ViewModel, используйте Двусторонние привязки в свойстве SelectedItem обоих ComboBox es и привяжите это к любомусвойство, которое вы имеете для него в ViewModel.

Если ваша коллекция может динамически меняться:

Если список стран (или что-то еще, что вы хотитечтобы использовать его для) может меняться во время выполнения, лучше всего, если вы реализуете INotifyPropertyChanged для класса Country и для регионов, используйте ObservableCollection<>.
Если его не нужно менять во время выполнения, нетнадо возиться с этим.

2 голосов
/ 09 июня 2010

Модель:

public ObservableCollection<Organisation> Organisations { get; set; }

private Organisation selectedOrganisation;
public Organisation SelectedOrganisation
{
  get { return this.selectedOrganisation; }
  set
  {
    if (this.selectedOrganisation != value)
    {
       this.selectedOrganisation = value;
       this.NotifyPropertyChanged("SelectedOrganisation");
       this.UpdateRegions();
    }
  }

  private IEnumerable<Region> regions;
  public IEnumerable<Region> Regions
  {
     get { return this.regions; }
     set
     {
        if (this.regions != value)
        {
          this.regions = value;
          this.NotifyPropertyChanged("Regions");
        }
     }
  }

  private void NotifyPropertyChanged(String info)
  {
    if (PropertyChanged != null)
    {
        PropertyChanged(this, new PropertyChangedEventArgs(info));
    }
  }

  private void UpdateRegions()
  {
    // If regions are not pre-populated you might need to perform a new call to 
    // the service that retrieves organisations in order to retrieve the associated Regions entities 
    // for the SelectedOrganisation organisation
    this.Regions = this.SelectedOrganisation.Regions;
  }

В вашем представлении:

<ComboBox x:Name="Organisations" ItemsSource="{Binding Organisations}" SelectedItem="{Binding SelectedOrganisation, Mode=TwoWay}" />
<ComboBox x:Name="Regions" ItemsSource="{Binding Regions}" />
...