Я разрабатываю внешнее приложение в C#/WPF, которое отображает информацию: Name
, Details
. Etc ...Раздел комментариев внутри каждого элемента списка ListBox
Я обрабатываю эту часть с помощью ListBox и простой привязки. Я заселить мою ListBox таким образом:
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="Assets\plus_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 Нажмите 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);
}
}
Извините за очень длинный пост, я надеюсь, что вы можете помочь моим на этом !
Вам не нужно заполнять свойство комментария класса A, но вы все равно сможете его связать. Таким образом, когда пользователь заполнит поле комментария, ваш объект ClassA будет содержать всю необходимую информацию – Sidewinder94
Вы имеете в виду без использования события PropertyChange? – SerpentSolide
Вам не нужно событие «PropertyChanged», если связанный элемент управления является единственным, кто изменит свойство. Это событие используется, чтобы сообщить другим объектам, которые будут зависеть от этого свойства, которое оно изменило, и они могут захотеть снова обновить/вычислить то, что они сделали с ним. – Sidewinder94