Это длинный. Я добавляю код, чтобы вы могли видеть, что я пытаюсь сделать. Дайте мне знать, если что-то не понятно
Я пытаюсь получить выбранные элементы из вложенного списка в многоцелевом режиме. Вот код (удалено много ненужных вещей)
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/
Я получаю представление с Item и SubItems.
1) Как лучше установить свойство IsSelected подэлементов из вложенного ListBox
Я добавлю команду, которая будет сохранять выбранный элемент в базе данных после двойного щелчка. Подэлементы будут сохранены как дочерняя запись на основе значения IsSelected.
2) Есть ли способ сделать свойство SubItems класса c # наблюдаемым. Я бы не хотел вносить изменения, добавив Observable к объекту, так как он будет в другой сборке и может использоваться другими приложениями.
Редактировать 1:
Нашел несколько полезный вопрос
WPF Привязка данных к шаблонам составных классов
Но опять же для этого мне придется наследовать от INotifyPropertyChanged.
Редактировать 2:
Позвольте мне посмотреть, смогу ли я объяснить лучше - ListBox1 - режим одиночного выбора, а parent & ListBox 2 - множественный выбор. ListBox1 привязан (источник элемента) к свойству, которое возвращает наблюдаемый набор. ListBox2 привязан к свойству в классе элементов (Item.SubItems), которое возвращает IList. Класс элемента имеет свойство IsSelected. Я хочу иметь возможность выбирать подэлементы, которые должны установить для свойства IsSelected для подэлементов значение true. Зная, что в Item Item нет наследования INotifyPropertyChanged, как мне этого добиться. Я предполагаю, что если подэлементы не попадают под некоторую наблюдаемую коллекцию, любые изменения не будут сообщаться обратно источнику. Используя свойство selectedData, я могу обновить подэлементы, найдя родительский Item, но затем, чтобы обновить представление, мне потребуется firePropertChanged для «items», который включает все элементы и подэлементы. Я хочу, чтобы только изменение подпунктов было уведомлено механизмом привязки. Извините, если мне все еще не ясно.
Редактировать 3:
Думаю, нет другого пути, кроме как реализовать INotifyPropertyChanged для класса Item. Другим способом было бы реализовать модель представления, которая очень специфична для потребностей представления, но это добавит много кода.