2016-04-19 4 views
0

Я пытаюсь напечатать 5 альбомов, и для каждого альбома распечатайте все свои песни с помощью флажка рядом с каждой песней. (Я рекомендую вам посмотреть изображение, опубликованное ниже) Я пытался сделать, чем с ItemsControl, но я не знаю, как это сделать, поэтому каждый ItemsControl свяжет другой список (с песнями конкретного альбома).Создайте элементы управления несколько раз с разными списками

Я сделал все 5 альбомов в цикле for.

Мои проблемы:

  1. Для каждого альбома, как я создаю ItemsControl для его список отдельных песен.
  2. Каждый раз, когда я проверяю CheckBox, он проверяет все флажки в своей строке « » (все остальные альбомы).

Вот код одного ItemsControl:

<ItemsControl Grid.Column="1" ItemsSource="{Binding}" 
        Grid.IsSharedSizeScope="True" 
        Margin="12 0 12 0"> 
     <ItemsControl.ItemTemplate> 
      <DataTemplate DataType="{x:Type domain:SelectableViewModel}"> 
       <Border x:Name="Border" Padding="8"> 
        <Grid> 
         <Grid.ColumnDefinitions> 
          <ColumnDefinition SharedSizeGroup="Checkerz" /> 
          <ColumnDefinition /> 
         </Grid.ColumnDefinitions> 
         <CheckBox VerticalAlignment="Center" IsChecked="{Binding IsSelected}"/> 
         <StackPanel Margin="8 0 0 0" Grid.Column="1"> 
          <TextBlock FontWeight="Bold" Text="{Binding Name}" /> 
          <TextBlock Text="{Binding Description}" /> 
         </StackPanel> 
        </Grid> 
       </Border> 
       <DataTemplate.Triggers> 
        <DataTrigger Binding="{Binding IsSelected}" Value="True"> 
         <Setter TargetName="Border" Property="Background" Value="{DynamicResource MaterialDesignSelection}" /> 

        </DataTrigger> 
       </DataTemplate.Triggers> 
      </DataTemplate> 
     </ItemsControl.ItemTemplate> 
    </ItemsControl> 

Это образ того, как это выглядит сейчас. (Смотреть на красные квадраты): Click here

Пожалуйста, помогите мне :(

ответ

0

попробуйте следующее решение:

Для каждого альбома, как я создаю ItemsControl для своего списка конкретные песни .

Udate # 1 - Xaml решение код

<Window x:Class="ListBoxOflistboxes.MainWindow" 
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation" 
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" 
    xmlns:listBoxOflistboxes="clr-namespace:ListBoxOflistboxes" 
    Title="MainWindow" Height="350" Width="525"> 

<Grid> 
    <Grid.Resources> 
     <DataTemplate x:Key="InnerItemsControl" DataType="{x:Type listBoxOflistboxes:AlbumViewModel}"> 
      <ItemsControl Grid.Column="1" ItemsSource="{Binding Songs}" 
       Grid.IsSharedSizeScope="True" 
       Margin="12 0 12 0"> 
       <ItemsControl.ItemTemplate> 
        <DataTemplate DataType="{x:Type listBoxOflistboxes:SelectableViewModel}"> 
         <Border x:Name="Border" Padding="8"> 
          <Grid> 
           <Grid.ColumnDefinitions> 
            <ColumnDefinition SharedSizeGroup="Checkerz" /> 
            <ColumnDefinition /> 
           </Grid.ColumnDefinitions> 
           <CheckBox VerticalAlignment="Center" IsChecked="{Binding IsSelected}"/> 
           <StackPanel Margin="8 0 0 0" Grid.Column="1"> 
            <TextBlock FontWeight="Bold" Text="{Binding Name}" /> 
            <TextBlock Text="{Binding Description}" /> 
           </StackPanel> 
          </Grid> 
         </Border> 
         <DataTemplate.Triggers> 
          <DataTrigger Binding="{Binding IsSelected}" Value="True"> 
           <Setter TargetName="Border" Property="Background" Value="Red" /> 
          </DataTrigger> 
          <DataTrigger Binding="{Binding IsSelected}" Value="False"> 
           <Setter TargetName="Border" Property="Background" Value="Transparent" /> 
          </DataTrigger> 
         </DataTemplate.Triggers> 
        </DataTemplate> 
       </ItemsControl.ItemTemplate> 
      </ItemsControl> 
     </DataTemplate> 
     <DataTemplate x:Key="ListBoxItemDataTemplate" DataType="listBoxOflistboxes:AlbumViewModel"> 
      <ContentControl Content="{Binding }" ContentTemplate="{StaticResource InnerItemsControl}"></ContentControl> 
     </DataTemplate> 
    </Grid.Resources> 
    <Grid.DataContext> 
     <listBoxOflistboxes:MainAlbumsViewModel/> 
    </Grid.DataContext> 

    <ListBox ItemsSource="{Binding Albums}"> 
     <ListBox.ItemsPanel> 
      <ItemsPanelTemplate> 
       <StackPanel Orientation="Horizontal"></StackPanel> 
      </ItemsPanelTemplate> 
     </ListBox.ItemsPanel> 
     <ListBox.ItemContainerStyle> 
      <Style TargetType="ListBoxItem"> 
       <Setter Property="Template"> 
        <Setter.Value> 
         <ControlTemplate TargetType="ListBoxItem"> 
          <Grid Margin="1"> 
           <Border x:Name="MouseOverBorder" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
             Background="LightGreen" BorderBrush="DimGray" BorderThickness="1.5" Visibility="Collapsed"/> 
           <Border x:Name="SelectedBorder" HorizontalAlignment="Stretch" VerticalAlignment="Stretch" 
             Background="Green" BorderBrush="Black" BorderThickness="1.5" Visibility="Collapsed"/> 
           <ContentPresenter Content="{TemplateBinding Content}" 
                ContentTemplate="{StaticResource ListBoxItemDataTemplate}" /> 
          </Grid> 
          <ControlTemplate.Triggers> 
           <!--Uncomment these trigger in order to make the mouse over border to be visible--> 
           <!--<Trigger Property="ListBoxItem.IsMouseOver" Value="True"> 
            <Setter TargetName="MouseOverBorder" Property="Visibility" Value="Visible"/> 
           </Trigger> 
           <Trigger Property="ListBoxItem.IsMouseOver" Value="False"> 
            <Setter TargetName="MouseOverBorder" Property="Visibility" Value="Collapsed"/> 
           </Trigger>--> 
           <Trigger Property="ListBoxItem.IsSelected" Value="True"> 
            <Setter TargetName="SelectedBorder" Property="Visibility" Value="Visible"/> 
           </Trigger> 
           <Trigger Property="ListBoxItem.IsSelected" Value="False"> 
            <Setter TargetName="SelectedBorder" Property="Visibility" Value="Collapsed"/> 
           </Trigger> 
          </ControlTemplate.Triggers> 
         </ControlTemplate> 
        </Setter.Value> 
       </Setter> 
      </Style> 
     </ListBox.ItemContainerStyle> 
    </ListBox> 

</Grid> 

Каждый раз, когда я проверить CheckBox он проверяет все галочки в строке (все остальные альбомы).

Managed в поле зрения-моделей с использованием общих моделей

/// <summary> 
/// main view model 
/// </summary> 
public class MainAlbumsViewModel:BaseObservableObject 
{ 
    private readonly ISelectionEventAggregator _selectionEventAggregator; 
    private readonly ISongsProvider _songsProvider; 

    private ObservableCollection<AlbumViewModel> _albums; 

    public MainAlbumsViewModel() 
    { 
     _selectionEventAggregator = new SelectionEventAggregator(); 
     _songsProvider = new SongsProvider(); 

     Albums = new ObservableCollection<AlbumViewModel> 
     { 
      new AlbumViewModel(_selectionEventAggregator, _songsProvider), 
      new AlbumViewModel(_selectionEventAggregator, _songsProvider), 
      new AlbumViewModel(_selectionEventAggregator, _songsProvider), 
     }; 

     Albums.ToList().ForEach(model => 
     { 
      _songsProvider.RegisterSongs(model, new List<SelectableViewModel> 
      { 
       new SelectableViewModel(_selectionEventAggregator){Name = "Song A", Description = "Description A"}, 
       new SelectableViewModel(_selectionEventAggregator){Name = "Song B", Description = "Description B"}, 
       new SelectableViewModel(_selectionEventAggregator){Name = "Song C", Description = "Description C"}, 
       new SelectableViewModel(_selectionEventAggregator){Name = "Song D", Description = "Description D"}, 
      }); 
     }); 
    } 

    public ObservableCollection<AlbumViewModel> Albums 
    { 
     get { return _albums; } 
     set 
     { 
      _albums = value; 
      OnPropertyChanged(); 
     } 
    } 
} 

/// <summary> 
/// an album view-model 
/// </summary> 
public class AlbumViewModel:BaseObservableObject 
{ 
    public AlbumViewModel(ISelectionEventAggregator selectionEventAggregator, ISongsProvider songsProvider) 
    { 
     _selectionEventAgreggator = selectionEventAggregator; 
     _songsProvider = songsProvider; 
     //you should think about an unsubscribe mechanism 
     _selectionEventAgreggator.SelectionEventHandler += SelectionEventAgreggatorOnSelectionEventHandler; 
    } 

    private void SelectionEventAgreggatorOnSelectionEventHandler(object sender, SelectionEventArgs args) 
    { 
     var key = args.Key as SelectableViewModel; 
     if(key == null) return; 
     var existingSong = Songs.FirstOrDefault(model => model.Name.Equals(key.Name) && model.Description.Equals(key.Description)); 
     if(existingSong == null) return; 
     existingSong.UpdateSelectionSilentely(args.IsSelected); 
    } 


    private ObservableCollection<SelectableViewModel> _songs; 
    private readonly ISelectionEventAggregator _selectionEventAgreggator; 
    private readonly ISongsProvider _songsProvider; 

    public ObservableCollection<SelectableViewModel> Songs 
    { 
     get { return _songs ?? (_songs = new ObservableCollection<SelectableViewModel>(_songsProvider.GetSongs(this))); } 
    } 
} 

/// <summary> 
/// helps to provide songs 
/// </summary> 
public interface ISongsProvider 
{ 
    List<SelectableViewModel> GetSongs(object albumKey); 
    void RegisterSongs(object albumKey, IEnumerable<SelectableViewModel> songs); 
} 

class SongsProvider : ISongsProvider 
{ 
    private Dictionary<object, List<SelectableViewModel>> _albums = new Dictionary<object, List<SelectableViewModel>>(); 
    public List<SelectableViewModel> GetSongs(object albumKey) 
    { 
     return _albums.ContainsKey(albumKey) == false ? null : _albums[albumKey]; 
    } 

    public void RegisterSongs(object albumKey, IEnumerable<SelectableViewModel> songs) 
    { 
     if (_albums.ContainsKey(albumKey) == false) 
     { 
      if(songs == null) return; 
      _albums.Add(albumKey, songs.ToList()); 
     } 
     else 
     { 
      if (songs == null) 
      { 
       _albums.Remove(albumKey); 
       return; 
      } 
      _albums[albumKey] = songs.ToList(); 
     } 
    } 
} 

    /// <summary> 
/// a single song view-model 
/// </summary> 
public class SelectableViewModel:BaseObservableObject 
{ 
    private readonly ISelectionEventAggregator _selectionEventAggregator; 
    private bool _isSelected; 
    private string _name; 
    private string _description; 

    public SelectableViewModel(ISelectionEventAggregator selectionEventAggregator) 
    { 
     _selectionEventAggregator = selectionEventAggregator; 
    } 

    public bool IsSelected 
    { 
     get { return _isSelected; } 
     set 
     { 
      _isSelected = value; 
      OnPropertyChanged(); 
      _selectionEventAggregator.Publish(new SelectionEventArgs {Key = this, IsSelected = _isSelected}); 
     } 
    } 

    public string Name 
    { 
     get { return _name; } 
     set 
     { 
      _name = value; 
      OnPropertyChanged(); 
     } 
    } 

    public string Description 
    { 
     get { return _description; } 
     set 
     { 
      _description = value; 
      OnPropertyChanged(); 
     } 
    } 

    public void UpdateSelectionSilentely(bool isSelected) 
    { 
     _isSelected = isSelected; 
     OnPropertyChanged(() => IsSelected); 
    } 
} 

/// <summary> 
/// helps to manage selection 
/// </summary> 
public interface ISelectionEventAggregator 
{ 
    event EventHandler<SelectionEventArgs> SelectionEventHandler; 

    void Publish(SelectionEventArgs selectionEventArgs); 
} 

public class SelectionEventAggregator : ISelectionEventAggregator 
{ 
    public event EventHandler<SelectionEventArgs> SelectionEventHandler; 
    public void Publish(SelectionEventArgs selectionEventArgs) 
    { 
     OnSelectionEventHandler(selectionEventArgs); 
    } 

    protected virtual void OnSelectionEventHandler(SelectionEventArgs e) 
    { 
     var handler = SelectionEventHandler; 
     if (handler != null) handler(this, e); 
    } 
} 

public class SelectionEventArgs:EventArgs 
{ 
    public object Key { get; set; } 
    public bool IsSelected { get; set; } 
} 

BaseObservableObject - простой INPC

/// <summary> 
/// implements the INotifyPropertyChanged (.net 4.5) 
/// </summary> 
public class BaseObservableObject : INotifyPropertyChanged 
{ 
    public event PropertyChangedEventHandler PropertyChanged; 

    protected virtual void OnPropertyChanged([CallerMemberName] string propertyName = null) 
    { 
     var handler = PropertyChanged; 
     if (handler != null) handler(this, new PropertyChangedEventArgs(propertyName)); 
    } 

    protected virtual void OnPropertyChanged<T>(Expression<Func<T>> raiser) 
    { 
     var propName = ((MemberExpression)raiser.Body).Member.Name; 
     OnPropertyChanged(propName); 
    } 

    protected bool Set<T>(ref T field, T value, [CallerMemberName] string name = null) 
    { 
     if (!EqualityComparer<T>.Default.Equals(field, value)) 
     { 
      field = value; 
      OnPropertyChanged(name); 
      return true; 
     } 
     return false; 
    } 
} 

Объяснение:

Основная идея второй части вашего вопроса - использовать какую-то агрегацию событий.

Как это выглядит here

С уважением.

+0

Спасибо за ваш ответ! BaseObservableObject не найден. Есть идеи? Можете ли вы выслать мне папку с проектом? – Rotem

+0

@RotemSimchi, пожалуйста, просмотрите обновления, я добавил BaseObservableObject. – Ilan

+0

Спасибо! Оно работает:). У меня последний вопрос: когда я с мышью на альбоме, вокруг него синяя квадрат, есть способ удалить его? ссылка на изображение: http://i.imgur.com/Bt9lmoN.png – Rotem

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