2014-09-05 1 views
0

Я пытаюсь создать представление, имеющее список расширителей, и я хочу, когда я нажимаю, чтобы развернуть один из них список имен из другого источника, который будет загружен , Пока что я получаю, когда я устанавливаю источник элемента в LineRouteCollection, чтобы установить заголовок расширителя, хотя я привязываю экспандер к отображению имен из AllStopsCollection, что привязка «Имя» показывает имена из источника LineRouteCollection, а не имена из AllStopsCollection, как я хочу. Можете ли вы взглянуть на мой код и рассказать мне, что я делаю неправильно?Catel MVVM Как установить два разных источника элемента в пределах одного ListBox

<ListBox> 
    <ItemsControl ItemsSource="{Binding LineRouteCollection}"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Expander Header="{Binding Name}" MinHeight="70">        
        <ListBox > 
         <ItemsControl ItemsSource ="{Binding AllStopsCollection}"> 
          <TextBlock Text="{Binding Name}"></TextBlock> 
         </ItemsControl> 
        </ListBox> 
       </Expander> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</ListBox> 

EDIT:

В моей модели представления я загружаю наблюдаемые коллекции (AllStopsCollection & LineRouteCollection), как это:

private ObservableCollection<Route> AllLineRoutes; 
private ObservableCollection<StopView> AllRouteStops; 

//List of all Routes connected to the selected line 
public ObservableCollection<Route> LineRouteCollection // Must be property or DP to be bound! 
{ 
    get { return AllLineRoutes; } 
    set 
    { 
     if (Equals(value, AllLineRoutes)) return; 
     AllLineRoutes = value; 
    } 
} 


//List of all stops 
public ObservableCollection<StopView> AllStopsCollection // Must be property or DP to be bound! 
{ 
    get { return AllRouteStops; } 
    set 
    { 
     if (Equals(value, AllRouteStops)) return; 
     AllRouteStops = value; 
    } 
} 

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

+0

Проблема в том, что вам нужно предоставить «ItemTemplate» вместо того, чтобы вставлять текстовое поле вместо «ItemsControl». У вас должна быть та же самая настройка, что и для первого 'ItemsControl' во внутреннем' ItemsControl' с элементом 'ItemsControl.ItemTemplate', содержащим текстовый блок, иначе область привязки для текстового блока является областью связывания первого' DataTemplate' – Charleh

+0

Я обновил свой ответ - ваша проблема связана с областями привязки (я ожидал, что у вас будет иерархия данных модели, а не две плоские коллекции!) – Charleh

ответ

1

Вы предоставили ItemTemplate для первых ItemsControl, но внутренний ItemsControl содержит TextBlock, который просто вложен внутри элемента управления

Вы должны указать ItemTemplate для внутреннего контроля слишком

<ListBox> 
    <ItemsControl ItemsSource="{Binding LineRouteCollection}"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate> 
       <Expander Header="{Binding Name}" MinHeight="70">        
        <ListBox> 
         <ItemsControl ItemsSource ="{Binding AllStopsCollection}"> 
          <ItemsControl.ItemTemplate> <!-- You forgot this ItemTemplate --> 
           <DataTemplate> 
            <TextBlock Text="{Binding Name}"></TextBlock> 
           </DataTemplate> 
          </ItemsControl.ItemTemplate> 
         </ItemsControl> 
        </ListBox> 
       </Expander> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 
</ListBox> 

В противном случае связывающую область для самой внутренней TextBlock собирается быть таким же, как внутренний ItemsControl, в результате чего вы видите

Не знаете, почему у вас есть ItemsControl внутри ListBox, хотя ..? Вам нужно несколько Expanders внутри ListBox, а не один элемент списка?

Это один работает для меня:

<ListBox ItemsSource="{Binding LineRoutes}"> 
     <ListBox.ItemTemplate> 
      <DataTemplate> 
       <Expander Header="{Binding Name}" MinHeight="70"> 
        <ListBox ItemsSource ="{Binding AllStops}"> 
          <ListBox.ItemTemplate> 
           <!-- You forgot this ItemTemplate --> 
           <DataTemplate> 
            <TextBlock Text="{Binding Name}"></TextBlock> 
           </DataTemplate> 
          </ListBox.ItemTemplate> 
        </ListBox> 
       </Expander> 
      </DataTemplate> 
     </ListBox.ItemTemplate> 
    </ListBox> 

Example of nested expanders in listbox

Это то, что вы хотели?

Edit:

Ok в свете ваших обновлений я могу увидеть, что ошибка

Вы хотите, чтобы ваши глаза для связывания ошибки в окне вывода.

AllStopsCollection не ребенок LineRouteCollection так в DataContext для внутреннего контроля указывает на Route а не ViewModel.

Для привязки к коллекции Stop s вам необходимо убедиться в том, что вы указываете привязку к элементу управления, который имеет ViewModel, так как это DataContext. Самый простой способ - использовать привязку ElementName и привязать ее к корневому управлению (обычно называемому LayoutRoot)

, например.

<Window x:Class="WpfApplication1.MainWindow" 
     xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
     xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
     xmlns:d="http://schemas.microsoft.com/expression/blend/2008" 
     xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006" 
     xmlns:wpfApplication1="clr-namespace:WpfApplication1" 
     mc:Ignorable="d" 
     Title="MainWindow" Height="350" Width="525" d:DataContext="{d:DesignInstance wpfApplication1:ViewModel}"> 
    <Grid Name="LayoutRoot"> 
     <ListBox ItemsSource="{Binding LineRouteCollection}"> 
      <ListBox.ItemTemplate> 
       <DataTemplate> 
        <Expander Header="{Binding Name}" MinHeight="70"> 
         <ListBox ItemsSource ="{Binding DataContext.AllStopsCollection, ElementName=LayoutRoot}"> <!-- Provide an ElementName binding to point to the root Grid and bind to the viewmodels AllStopsCollection (viewmodel is in the DataContext) --> 
          <ItemsControl.ItemTemplate> 
           <DataTemplate> 
            <TextBlock Text="{Binding Name}"></TextBlock> 
           </DataTemplate> 
          </ItemsControl.ItemTemplate> 
         </ListBox> 
        </Expander> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
    </Grid> 
</Window> 

Надежда, что помогает

Единственное, что нужно следить за то, если вам нужно манипулировать стоп - очевидно, так как вы связывании тот же набор для нескольких вложенных списков, если вы измените Stop элемент его также изменит значения в каждом из списков, так как ссылки все указывают на один и тот же объект.

+0

Хм, я думаю, что вы правы в ItemTemplate, но теперь, я исправил его, проблема остается, теперь она ничего не показывает. Но я думаю, что вы положили меня на правильный путь. – user3182266

+0

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

+0

. Хорошо, я обновил, похоже, вы пытаетесь вложить ' Элементы управления ItemsControl' - 'ListBox' * - это' ItemsControl', поэтому вам не нужно встраивать внутри 'ListBox'. Я предполагаю, что вы хотите два списка, один вложенный внутри другого с разными источниками предметов. – Charleh

-1

Это один из подходов, постарайтесь быть более динамичными. Вот список, в котором я предопределил 3 разных текстовых поля и предоставил значения во время выполнения.

<ListBox x:Name="ListBox1" HorizontalAlignment="Left" Height="253" Margin="10,28,0,0" VerticalAlignment="Top" Width="734"> 
        <ListBox.ItemTemplate> 
         <DataTemplate> 
          <Grid x:Name="grid" Margin="0,2"> 
           <Grid.ColumnDefinitions> 
            <ColumnDefinition Width="*" /> 
            <ColumnDefinition Width="234" /> 
            <ColumnDefinition Width="143" /> 
           </Grid.ColumnDefinitions> 
           <TextBlock Grid.Column="0" HorizontalAlignment="Left" Text="{Binding String1}"/> 
           <TextBlock Grid.Column="1" HorizontalAlignment="Left" Text="{Binding String2}" TextTrimming="WordEllipsis"/> 
           <TextBlock Grid.Column="2" HorizontalAlignment="Left" Text="{Binding String3}"/> 
          </Grid> 
         </DataTemplate> 
        </ListBox.ItemTemplate> 
       </ListBox> 

Код За:

public class Class1 
    { 
     public string String1 { get; set; } 
     public string String2 { get; set; } 
     public string String3 { get; set; } 
    } 

    private void Button1_Click(object sender, RoutedEventArgs e) 
    { 
      ListBox1.Items.Add((new Class1() 
      { 
       String1 = "Apple", 
       String2 = "Car", 
       String3 = "Tree" 
      })); 
    } 

ИЛИ

Если вы хотите решение, которое является более динамичным во время выполнения, вы можете сделать что-то вроде этого:

private void Button1_Click(object sender, RoutedEventArgs e) 
    { 
       Grid WholeGrid = new Grid(); 
       WholeGrid.HorizontalAlignment = HorizontalAlignment.Left; 
       ColumnDefinition colDef1 = new ColumnDefinition(); 
       ColumnDefinition colDef2 = new ColumnDefinition(); 
       ColumnDefinition colDef3 = new ColumnDefinition(); 
       WholeGrid.ColumnDefinitions.Add(colDef1); 
       WholeGrid.ColumnDefinitions.Add(colDef2); 
       WholeGrid.ColumnDefinitions.Add(colDef3); 

       // Create Question Lable 
       Label QuestionLabel = new Label(); 
       QuestionLabel.Content = "Apple"; 
       Grid.SetRow(QuestionLabel, 0); 
       Grid.SetColumn(QuestionLabel, 0); 

       // Create Date Picker 
       DatePicker newDatePicker = new DatePicker(); 
       newDatePicker.Width = 200; 
       newDatePicker.Height = 20; 
       Grid.SetRow(newDatePicker, 0); 
       Grid.SetColumn(newDatePicker, 1); 

       // Add to Lable and Date Picker 
       WholeGrid.Children.Add(QuestionLabel); 
       WholeGrid.Children.Add(newDatePicker); 
       ListBox1.Items.Add(WholeGrid); 
    } 
+0

Это не очень дружественный к MVVM способ сделать что-либо, а также не отвечает Вопрос OPs каким-либо образом – Charleh