2016-08-24 4 views
0

Я хотел бы иметь список TextBlocks с ComboBoxes рядом с каждым из них. Источник данных ComboBoxes должен быть одинаковым для каждого ComboBox. Однако каждый TextBlock должен содержать секвенциальный элемент списка Оба источника данных для ComboBoxs и TextBlocks находятся в моем объекте «Настройки». Поэтому я установил DataContext для всего окна в этот объект настроек.Правильно установить источник привязки в XAML

Вот моя проблема: Источник данных TextBlock: Список называется полями, которые находятся внутри объекта под заголовком «Заголовок» типа «Линия» (который, конечно же, находится в объекте настроек, который является моим datacontext).

Таким образом, графически: настройки (тип: Настройка) - заголовок (тип: CsvLine) - Поля (тип: Список строки)

Теперь ComboBox. Источник данных каждого ComboBox должен быть списком под названием Метка

Графический: Настройки (типа: Настройка) - Тэги (типа: Список строки)

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

Вот мой код:

<Grid> 
    <StackPanel Orientation="Horizontal"> 
     <ItemsControl ItemsSource="{Binding Headers}"> 
      <ItemsControl.ItemTemplate> 
       <DataTemplate> 
        <StackPanel Orientation="Horizontal"> 
         <TextBlock Text="{Binding Fields}"/> 
         <ComboBox ItemsSource="{Binding DataContext.Tags, 
          RelativeSource={RelativeSource AncestorType=ItemsControl}}"> 
         </ComboBox> 
        </StackPanel> 
       </DataTemplate> 
      </ItemsControl.ItemTemplate> 
     </ItemsControl> 
    </StackPanel> 
</Grid> 

Я понятия не имею, что я должен фактически передать, как ItemsSource для ItemsControl, потому что я думаю, что это должно быть общим источником для обоих TextBoxes и ComboBoxes, но их единственный общий источник установки объект - но я уже установил его как свой DataContext. Я использовал RelativeSource в ComboBox, но я не уверен, для чего он используется (хотя я читал статью об этом в MSDN). Я не знаю, почему, но мне очень сложно понять привязанность - я изо всех сил пытаюсь заставить что-то работать.

// EDIT: Вот мой класс Настройки - что тип моих настроек объекта:

public class Settings 
{ 
    public CsvLine AllHeaders1 
    { 
     get 
     { 
      return _allHeaders1; 
     } 
    } 

    public CsvLine _allHeaders1 = new CsvLine() 
    { 
     Fields = new List<string>() 
     { 
      "Header1" , "Header2" , "Header3" 
     } 
    }; 

    private List<String> _tags; 

    public List<String> Tags 
    { 
     get 
     { 
      return new List<string>() { "Tag1", "Tag2", "Tag3", "Tag4", "Tag5" }; 
     } 
     set 
     { 
      _tags = value; 
     } 
    } 

} 

А вот мой CsvLine класс:

public class CsvLine 
{ 
    public List<string> Fields = new List<string>(); 

    public int LineNumber; 

} 
+0

Не похоже, что вы на расстоянии миллиона миль. Не могли бы вы разместить свой объект настроек, так как сложно описать его описание? Конечно, привязка в TextBlock '{Binding Fields}' неверна, учитывая, что в вашем описании Fields - это список строк. – ibebbs

+0

Конечно, я добавлю это через минуту – Loreno

ответ

1

Таким образом, я не 100 % уверен в том, чего вы хотите, но следующее должно начаться.

Во-первых, вам необходимо убедиться, что вы привязываетесь к общедоступным объектам - не к публичным элементам - поэтому член CsvLine.Fields должен быть изменен на public List<string> Fields { get { return _fields; } set { _fields = value; } }. Кроме того, если вы хотите, чтобы изменения в объекте настроек отражались в пользовательском интерфейсе, вам необходимо реализовать INotifyPropertyChanged.

В любом случае, с этим на месте и назначенным DataContext сетки, следующий будет отображать вертикальный список текстовых блоков (показывая «Заголовок 1», «Заголовок 2», «Заголовок 3»), каждый из которых имеет комбо поле справа, содержащее значения «Tag1», «Tag2» ... «Tag5».

<Grid x:Name="SourceGrid"> 
    <ItemsControl ItemsSource="{Binding Path=AllHeaders1.Fields}"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <StackPanel Orientation="Horizontal"> 
        <TextBlock Text="{Binding}" /> 
        <ComboBox ItemsSource="{Binding ElementName=SourceGrid, Path=DataContext.Tags}" /> 
       </StackPanel> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</Grid> 

Надеюсь, что это поможет.

+0

Удивительно, это работает! Как вы узнали, как это должно быть связано?Я имею в виду, почему вы привязывали ItemsControl к AllHeaders.Fields? Разве это не относится к ComboBoxes, так как они находятся внутри этого элемента ItemsControl? Почему это не работает, если я привязываю TextBlock непосредственно к Allheaders1.Fields? – Loreno

+0

TextBlock может отображать только один элемент контента и не ожидает коллекцию, поэтому попытается вызвать «.ToString()» на объекте, к которому он привязан. Я ожидал бы, что когда вы привязали коллекцию Allheaders.Fields к TextBlock, она отобразила что-то вроде «List <'a>» (т. Е. Имя класса, связанного с TextBlock). Независимо от того, да, DataContext будет течь из ItemsControl в ComboBox, поэтому вам потребуется длинная ручная привязка для ComboBox ItemsSource, которая указывает элемент для привязки и относится именно к его DataContext. – ibebbs

+0

ОК, но если вы привязали AllHeaders1.Fields к ItemsControl, TextBlock также получает это ограничение, но он не отображает «Список » - он правильно отображает содержимое этого списка. Как оно это делает? – Loreno

Смежные вопросы