Раздел комментариев внутри каждого элемента списка

Я разрабатываю внешнее приложение в C# / WPF, которое отображает информацию : Name, Details. Так далее…

Я обрабатываю эту часть со списком и простой привязкой. Я заполняю список таким образом :

 model.ClassAs.Add(new ClassA { Name = textBox1.Text, Detail = textBox2.Text });

Проблема пришла сейчас : теперь я должен реализовать Comment Sectionдля пользователей, чтобы добавить комментарии внутри каждого ListBoxItemsотдельно. Очевидно, я не могу заполнитьComment Section, когда я заполняю Nameи Details. Поэтому я создаю второе ListBox внутри ItemsTemplateпервого, ListBoxSeption, если хотите. Я создаю другой класс ClassBи пытаюсь реализовать привязку, как в первый раз.

Очевидно, это не сработало, потому что я был в DataContext ListBox1. Я пытаюсь настроить ObservableCollectionс PropertyChangedсобытием, но я не могу заставить его работать. Я не очень хорошо понимаю этот процесс, поэтому я не вижу, где моя ошибка.

Вот мой XAML:

<ListBox x_Name="listBox" MouseDoubleClick="ListBox_MouseDoubleClick"
             ScrollViewer.HorizontalScrollBarVisibility="Disabled" HorizontalContentAlignment="Stretch"
             ItemsSource="{Binding ClassAs, Mode=OneWay}" Grid.Column="1" >
    <ListBox.ItemTemplate>
        <DataTemplate>
            <Grid x_Name="grd">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="100"/>
                </Grid.ColumnDefinitions>
                <Grid.RowDefinitions>
                    <RowDefinition Height="auto"/>
                </Grid.RowDefinitions>
                <TextBlock Name="Name" Text="{Binding Name, Mode=OneWay}" Grid.Column="2" Foreground="DarkGray" FontWeight="Bold" />
                <TextBlock Text="{Binding Detail, Mode=OneWay}" Grid.Column="2" Grid.Row="1" TextWrapping="Wrap" />
                <Grid x_Name="comSection" Visibility="{Binding RelativeSource={RelativeSource AncestorType={x:Type ListBoxItem}}, Path=IsSelected, Converter={StaticResource booleanVisibleConverter}}"
                      Grid.Column="2" Grid.Row="2">
                    <Grid.ColumnDefinitions>
                        <ColumnDefinition Width="*"/>
                    </Grid.ColumnDefinitions>
                    <Grid.RowDefinitions>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
                    <AdornerDecorator>
                        <TextBox x_Name="textBoxCom" HorizontalAlignment="Stretch"
                    TextWrapping="Wrap" Grid.Column="0" Grid.Row="0">
                            <controls:WatermarkService.Watermark>
                                <TextBlock>Type Comment Here...</TextBlock>
                            </controls:WatermarkService.Watermark>
                        </TextBox>
                    </AdornerDecorator>
                    <ListBox x_Name="listBoxCom" BorderThickness="0,0,0,0" Grid.Row="1" Grid.Column="0"
                             HorizontalContentAlignment="Stretch" VerticalContentAlignment="Stretch" VerticalAlignment="Stretch" ScrollViewer.VerticalScrollBarVisibility="Visible"
                             ItemsSource="{Binding ClassBs.Commentary}">
                        <ListBox.ItemTemplate>
                            <DataTemplate>
                                <Grid>
                                    <Grid.RowDefinitions>
                                        <RowDefinition Height="20"/>
                                        <RowDefinition Height="20"/>
                                    </Grid.RowDefinitions>
                                    <TextBlock Name="TBCom" Text="{Binding}"></TextBlock>
                                </Grid>
                            </DataTemplate>
                        </ListBox.ItemTemplate>
                    </ListBox>
                </Grid>
                <Button x_Name="addComment" HorizontalAlignment="Center" VerticalAlignment="Top" Width="25" Height="25"
                        BorderThickness="0" Click="addComment_Click" Background="Transparent" Grid.Column="1" Grid.Row="2"
                        ToolTip="Comment">
                    <Button.Content>
                        <Image Source="Assetsplus_orange.png" />
                    </Button.Content>
                </Button>
            </Grid>
        </DataTemplate>
    </ListBox.ItemTemplate>
</ListBox>

Что я хочу: пользователь заполнить textBoxComи нажмите addCommentкнопку, чтобы добавить комментарий в выбранном ListBoxItem.

мой класс :

public sealed class ClassA : INotifyPropertyChanged
{
    public string Name { get; set; }
    public string Detail { get; set; }

    public ObservableCollection<ClassB> ClassBs { get; set; }
    public List<ClassB> ModifiedComments { get; set; }

    public event PropertyChangedEventHandler PropertyChanged;

    public class ClassB
    {
        string Commentary { get; set;}
    }
}

Моя ViewModel :

public sealed class ViewModel
{
    public ObservableCollection<ClassA> ClassAs { get; set; }
    public ObservableCollection<ClassA.ClassB> ClassBs { get; set; }

    List<ClassA.ClassB> ModifiedItems { get; set; }

    public ViewModel()
    {
        ClassAs = new ObservableCollection<ClassA>();
        CLassBs = new ObservableCollection<ClassA.ClassB>();
        ModifiedItems = new List<ClassA.ClassB>();
        this.ClassBs.CollectionChanged += this.OnCollectionChanged;
    }

    void OnCollectionChanged(object sender, NotifyCollectionChangedEventArgs e)
    {
        try
        {
            if (e.NewItems != null)
            {
                foreach (ClassA.ClassB newItem in e.NewItems)
                {
                    ModifiedItems.Add(newItem);

                    //Add listener for each item on PropertyChanged event
                    newItem.PropertyChanged += this.OnItemPropertyChanged;
                }
            }

            if (e.OldItems != null)
            {
                foreach (ClassA.ClassB oldItem in e.OldItems)
                {
                    ModifiedItems.Add(oldItem);

                    oldItem.PropertyChanged -= this.OnItemPropertyChanged;
                }
            }
        }
        catch(Exception ex)
        {
            MessageBox.Show("me : " + ex);
        }
        }

    void OnItemPropertyChanged(object sender, PropertyChangedEventArgs e)
    {
        ClassA.ClassB item = sender as ClassA.ClassB;
        if (item != null)
            ModifiedItems.Add(item);
    }
} 

My Click Event (AddComment)

private void addComment_Click(object sender, RoutedEventArgs e)
{
    try
    {
        currentSelectedListBoxItem = this.listBox.ItemContainerGenerator.ContainerFromIndex(listBox.SelectedIndex) as ListBoxItem;
        System.Windows.Controls.TextBox textBoxCom = Helper.FindDescendant<System.Windows.Controls.TextBox>(currentSelectedListBoxItem);
        ListBox LBCom = Helper.FindDescendant<ListBox>(currentSelectedListBoxItem);
        if (string.IsNullOrWhiteSpace(textBoxCom.Text))
            MessageBox.Show("Please fill the Comment Section");
        else
        {
            model.ClassBs.Add(new ClassA.ClassB { Commentary = textBoxCom.Text });
            textBoxCom.Clear();

        }
    }
    catch (Exception exp)
    {
        MessageBox.Show("exp = " + exp);
    }
}

Извините за очень длинный пост, я надеюсь, что вы можете помочь мне в этом !

1 ответ

  1. Ну, это было проще, чем ожидалось, я просто копался в бесполезном коде!
    I get rid of all the code about ObservableCollectionand PropertyChangeEvent.

    Мой окончательный код ClassA (больше нет ClassB) :

    public sealed class ClassA
    {
    
    
        public string Name { get; set; }
        public string Detail { get; set; }
        public List<string> Comments { get; set; }
    
        public Issue()
        {
            Comments = new List<string>();
        }
    }
    

    И мое последнее событие щелчка :

    var selected = listBox.SelectedItem as ClassA;
                    selected.Comments.Add(textBoxCom.Text);
                    listBox.Items.Refresh();
                    textBoxCom.Clear();
    

    Спасибо @Sidewinder94 !