Как привязать «список» строк к ComboBox в WPF? - PullRequest
3 голосов
/ 27 июля 2011

Я хочу взять несколько имен в коллекции и связать их со списком. Например:

  • Bill
  • Jack
  • Bob
  • Kevin

и иметь эти элементы в коллекции и привязать их к ComboBox. Я не уверен, будет ли список обновляться динамически или нет, но я предпочитаю планировать это. Любая помощь будет оценена. Я пытался в течение нескольких часов и не могу понять это. Я хочу сделать это в XAML, а не в коде. В коде позади,

MyComboBox.ItemsSource = MyObservableCollection; 

отлично работает. Я не знаю, как это сделать в XAML, хотя с коллекцией, объявленной в коде.

Заранее спасибо (еще раз), сообщество.

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

Вот так я объявил коллекцию и стал доступен.

    public ObservableCollection<string> propertynames 
    { 
        get {return _propertynames;}
    }
    private ObservableCollection<string> _propertynames;

Последнее, что я попробовал, было это:

<Window.Resources>     
    <CollectionViewSource Source="{Binding propertynames}" x:Key="srcSort"/>
</Window.Resources>
....
    <ComboBox x:Name="cboSort" HorizontalAlignment="Left" VerticalAlignment="Top" 
              Width="256" Background="WhiteSmoke" Margin="12,50,0,0" FontSize="12pt" 
              Height="27.28" 
              SelectedIndex="0" 
              SelectionChanged="cboWorkCenters_SelectionChanged"
              ItemsSource="{Binding Path = {StaticResource srcSort}}">
    </ComboBox>
....

Я всего лишь n00b. Занимался этим около недели, поэтому я мог сделать что-то действительно очевидное для опытного пользователя.

* РЕДАКТИРОВАТЬ # 2

<Window x:Class="WpfApplication1.Window1"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    xmlns:s="clr-namespace:WpfApplication1"
    Title="Window1" Height="226" Width="242"
    DataContext="{Binding RelativeSource={RelativeSource Self}}">

    <Grid>
        <ComboBox Margin="43,71,40,77" 
                  Name="comboBox1" 
                  ItemsSource="{Binding ob}" />
    </Grid>
</Window>

namespace WpfApplication1
{
    /// <summary>
    /// Interaction logic for Window1.xaml
    /// </summary>
    public partial class Window1 : Window
    {
        public ObservableCollection<string> ob 
        { 
            get 
            {
                return _ob;
            }
        }
        private ObservableCollection<string> _ob = new ObservableCollection<string>();

        public Window1()
        {
            InitializeComponent();
            FillObj();
            //comboBox1.ItemsSource = ob;
        }

        private void FillObj()
        {
            for (int i = 1; i < 6; i++)
            {
                _ob.Add(i.ToString());
            }
        }
    }
}

Сделанный выше настоящий простой проект, просто чтобы посмотреть, правильно ли я все делал. Это работало нормально, поэтому что-то еще могло вызывать его сбой.

* РЕДАКТИРОВАТЬ # 3 * ИСПРАВЛЕНО ПРОБЛЕМА

Ради Бога, я понял это. Я был на этом в течение ЧАСОВ, и это просто глупо, что заставило его потерпеть неудачу.

Решение заключается в следующем: я не создавал экземпляров _propertynames, когда объявил об этом. Я запрашивал свойства класса с помощью Linq, чтобы получить список свойств, а затем создал _propertynames, передав ... GetProperties.ToList <...> () в конструктор. По-видимому, вам нужно создать экземпляр переменной, чтобы она вошла во время InitializeComponent. Нереально. Как только я сделал это, а затем добавил элементы после него, он работал нормально.

Я бы хотел, чтобы у WPF было лицо, чтобы я мог ударить его. Я знаю, что это мое незнание того, как это работает, но я действительно мог бы использовать какое-то сообщение.

Спасибо, ребята, за помощь. Оба ваших предложения были полезны, как только я позаботился о коренной проблеме.

private ObservableCollection<string> _propertynames

должно быть

private ObservableCollection<string> _propertynames = new ObservableCollection<string>()

Ответы [ 2 ]

4 голосов
/ 27 июля 2011

Есть бесчисленное множество способов сделать это. После того как вы создали коллекцию в коде, вы можете:

  1. Вызовите Resources.Add, чтобы добавить его в словарь ресурсов окна, а затем связать с ресурсом, например, ItemsSource="{Binding {DynamicResource MyList}}".

  2. Дайте ComboBox имя (используя атрибут x:Name) и установите его ItemsSource явно в коде, например. MyComboBox.ItemsSource = myCollection;.

  3. Создайте класс, сделайте коллекцию свойством класса и установите для DataContext окна экземпляр этого класса и привязайте его напрямую, например, ItemsSource = "{Binding MyCollectionProperty}".

  4. Сделайте коллекцию свойством окна, установите для DataContext окна значение this и свяжите со свойством (это по сути та же техника, что и в # 3, только вы не создаете новый класс).

  5. Не устанавливая DataContext окна, вы все равно можете ссылаться на свойство в нем, используя привязку, если вы дали ему имя, например, {Binding ElementName=MyWindow, Path=MyCollection}. (Это то же самое, что предложение Росса.)

  6. Или, не давая окну имя, вы можете использовать RelativeSource привязку, чтобы найти предка Window и привязать к нему свойство. Я не уверен в своей способности написать рабочее связывающее выражение, которое использует RelativeSource в верхней части моей головы, поэтому я оставлю это в качестве упражнения для читателя.

  7. Вы можете установить DataContext из ComboBox для экземпляра вашей коллекции, а затем установить для ItemsSource значение {Binding}. Вы вероятно не сделали бы это на практике; Я упоминаю об этом только потому, что для людей является обычной ошибкой устанавливать DataContext элемента управления без установки привязки, а затем удивляться, почему содержимое связанного объекта не отображается.

(Хотя я сказал «окно» выше, все, что я сказал, верно и для пользовательских элементов управления.)

Я уверен, что есть как минимум пять других способов сделать это, о которых я не думаю. Связывание действительно очень гибкое.

2 голосов
/ 27 июля 2011

Что вы пробовали до сих пор?

Я бы подошел к этому следующим образом, предполагая, что поле со списком находится внутри UserControl с классом code-behind, содержащим свойство public MyObservableCollection:

<UserControl x:Name="MyCollectionOwnerControl">

    <ComboBox ItemsSource="{Binding ElementName=MyCollectionOwnerControl, Path=MyObservableCollection, Mode=OneWay}" />

</UserControl>
...