私は、情報を表示するC#/ WPFで外部アプリケーションを開発しています:Name
、Details
。その他...各ListBox内のコメントセクション
私はこの部分をListBoxと単純バインディングで処理します。私は私のリストボックスを移入この方法:
model.ClassAs.Add(new ClassA { Name = textBox1.Text, Detail = textBox2.Text });
問題は今来る:私は今、別途各ListBoxItems
の内側にコメントを追加するユーザーのためComment Section
を実装する必要があります。明らかに、Name
とDetails
を入力するとComment Section
を入力できません。だから、最初の1つのItemsTemplate
のListBoxSeptionの中に2番目のListBoxを作成します。私は他のクラスClassB
を作成し、初めてのようにバインディングを実装しようとします。
明らかに、私はListBox1のDataContextにあったので、それは動作しませんでした。私はPropertyChanged
イベントでObservableCollection
を設定しようとしましたが、動作させることができません。私はこのプロセスをとてもうまく理解していないので、私のエラーがどこにないか分かりません。ここで
は私の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
を記入し、選択ListBoxItemにコメントを追加するaddComment
ボタンを押してください。
私のクラス:
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);
}
}
私のClickイベント(で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