2009-09-17 3 views
0

Это длинный. Я добавляю код, чтобы вы могли видеть, что я пытаюсь сделать. Дайте мне знать, если что-то неясноWPF Вложенная привязка ListBox с использованием ViewModel

Я пытаюсь получить выбранные элементы из вложенного списка в многосегментном режиме. Вот код (удален много нежелательного материала)

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

    public IList<Item> SubItems { get; set; } // 

    public bool IsSelected { get; set; } 
} 
//Chicken Fried Chicken 
//A hearty boneless chicken breast, lightly breaded in our special seasonings and 
//golden fried. Served with garlic mashed potatoes, country gravy and seasonal vegetables 
// from Applebees 

//Item - Chicken Fried Chicken 
//SubItem- mashed potatoes 
//SubItem- country gravy 
//SubItem- seasonal vegetables 
//SubItem- Fries 
//SubItem- Sauted vegetables 
//SubItem- House Salad 

public class ItemViewModel : INotifyPropertyChanged, IItemViewModel 
{ 


    ObservableCollection<Item> selectedData = new ObservableCollection<Item>(); 

    private ObservableCollection<Item> todaysItems; 
    public ObservableCollection<Item> TodaysItems 
    { 
     get { return todaysItems; } 
     private set 
     { 
      if (todaysItems != value) 
      { 
       todaysItems = value; 
       PropertyChanged(this, new PropertyChangedEventArgs("todaysItems")); 
      } 
     } 
    } 



    public ItemViewModel(IItemView itemView) 
    { 
     this.View = itemView; 
     this.View.Model = this; 

     List<Item> items = service.GetAllTestItems(); 
     TodaysItems = new ObservableCollection<Item>(items); 

     selectedData.CollectionChanged += (sender, e) => UpdateSummary(); 
    } 



    #region INotifyPropertyChanged Members 

    public event PropertyChangedEventHandler PropertyChanged = delegate { }; 
    private void NotifyPropertyChanged(string propertyName) 
    { 
     var handler = this.PropertyChanged; 
     if (handler != null) 
     { 
      handler(this, new PropertyChangedEventArgs(propertyName)); 
     } 
    } 
    #endregion 


    // How to get Selected Items from ListBox 

    public ObservableCollection<Item> SelectedData 
    { 
     get { return selectedData; } 
     set 
     { 
      selectedData = value; 
     } 
    } 


    private void UpdateSummary() 
    { 
     // here I can get selected data , I can find which Item is selected and then update its SubItems IsSelected (CLR) Property 
     // but something is not right here 
    } 
} 

XAML

<UserControl x:Class="ItemView" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:prism="clr-namespace:Microsoft.Practices.Composite.Presentation.Commands;assembly=Microsoft.Practices.Composite.Presentation" 
      xmlns:ZCom="clr-namespace:MyProj.Infrastructure;assembly=Infrastructure"> 

    <Grid > 
     <ListBox ItemsSource="{Binding TodaysItems}"> 
      <ListBox.ItemTemplate> 
       <DataTemplate > 
        <Border BorderThickness="1,1,1,1" CornerRadius="2,2,2,2" BorderBrush="Black"> 
         <Grid MinHeight="50" Width="150" Height="Auto" Margin="0,0,0,0"> 
          <Grid.RowDefinitions> 
           <RowDefinition /> 
           <RowDefinition/> 
           <RowDefinition /> 
          </Grid.RowDefinitions> 
          <Grid.ColumnDefinitions> 
           <ColumnDefinition Width="150"/> 
           <ColumnDefinition Width="0"/> 
          </Grid.ColumnDefinitions> 
          <TextBlock Margin="4,4,2,2" Grid.Row="0" Width="Auto" TextWrapping="Wrap" Text="{Binding Path=Name}" /> 
          <Grid Grid.Row="2" Grid.Column="0" Grid.ColumnSpan="2" > 
           <Grid.Style> 
            <Style> 
             <Style.Triggers> 
              <DataTrigger Binding="{Binding Path=IsSelected, RelativeSource= 
                    {RelativeSource Mode=FindAncestor,AncestorType={x:Type ListBoxItem}} 
              }" Value="false"> 
               <Setter Property="Grid.Visibility" Value="Collapsed"/> 
              </DataTrigger> 
             </Style.Triggers> 
            </Style> 
           </Grid.Style> 
           <Grid.RowDefinitions> 
            <RowDefinition Height="35"/> 
            <RowDefinition Height="*"/> 
           </Grid.RowDefinitions> 
           <TextBlock Margin="2,4,2,2" Grid.Row="0" Width="Auto" FontSize="10" FontStyle="Italic" TextWrapping="Wrap" Text="{Binding Path=Note}"/> 

           <ListBox Style="{DynamicResource MyStyle}" Grid.Row="1" ItemsSource="{Binding Path=Modifiers}" SelectionMode="Multiple" 
             ZCom:ListBoxHelper.SelectedItems="{Binding RelativeSource={RelativeSource FindAncestor, AncestorType={x:Type UserControl}}, Path=DataContext.SelectedData}"> 
            <ListBox.ItemTemplate> 
             <DataTemplate > 
              <TextBlock Margin="2,2,2,2" TextWrapping="Wrap" Text="{Binding Path=Name}" /> 
             </DataTemplate> 

            </ListBox.ItemTemplate> 
           </ListBox> 
          </Grid> 

         </Grid> 
        </Border> 
       </DataTemplate> 
      </ListBox.ItemTemplate> 
     </ListBox> 
    </Grid> 
</UserControl> 

Я использую ListBoxHelper (в инфраструктуре) от http://marlongrech.wordpress.com/2009/06/02/sync-multi-select-listbox-with-viewmodel/

я получаю вид с п и подпункты.

1), что лучше способ установить IsSelected свойство подпунктов от вложенной ListBox

Добавлю команду, которая будет хранить выбранный элемент базы данных один раз двойной щелчок. SubItems будет храниться как дочерняя запись на основе значения IsSelected.

2) Есть ли способ сделать свойство SubItems класса C# наблюдаемым. Я бы не хотел меняться, добавляя Observable к объекту, так как он будет в другой сборке и может использоваться другими приложениями.

Edit 1: Найдено несколько полезно вопрос

WPF Databinding to composite class patterns

Но опять-таки для этого мне придется наследовать от INotifyPropertyChanged.

Edit 2: Позвольте мне увидеть, если я могу объяснить лучше- listbox1 Одинокий выберите режим и родительский & ListBox 2 является множественный. ListBox1 привязан (источник источника) к свойству, которое возвращает наблюдаемое объединение. ListBox2 привязан к свойству класса Item (Item.SubItems), который возвращает IList. Класс объекта имеет свойство IsSelected. Я хочу иметь возможность выбирать подэлементы, которые должны установить значение IsSelected Property для subItems в true. Зная, что в классе предметов нет INotifyPropertyChanged наследования, как я могу это достичь. Я предполагаю, что, если подэлементы не подпадают под какую-либо наблюдаемую коллекцию, любые изменения не будут отправлены обратно в источник. Используя свойство selectedData, я могу обновить подэлементы, найдя родительский элемент, но затем обновить представление, которое мне нужно будет для firePropertChanged для «элементов», которое включает в себя все элементы и подэлементы. Я хочу, чтобы только изменения подтитов были уведомлены обратно механизмом привязки. Извините, если я еще не понял.

Edit 3:

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

ответ

0

Это немного запутанно, что ваша общая цель здесь.

Если вы просто пытаетесь получить выбранные элементы из вложенного списка ListBox, попытались ли вы предоставить ListBox x:Name и разоблачить ваши SelectedItems через свойство в вашем классе UserControl (ItemView)?

public IList SelectedItems 
{ 
    get { return nestedListBox.SelectedItems; } 
} 
+0

@ Guard- См. Изменение 2. Я попытался написать его как комментарий, но он стал слишком длинным – TheMar

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