2016-05-24 1 views
0

私は、情報を表示するC#/ WPFで外部アプリケーションを開発しています:NameDetails。その他...各ListBox内のコメントセクション

私はこの部分をListBoxと単純バインディングで処理します。私は私のリストボックスを移入この方法:

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

問題は今来る:私は今、別途各ListBoxItemsの内側にコメントを追加するユーザーのためComment Sectionを実装する必要があります。明らかに、NameDetailsを入力すると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); 
    } 
} 

非常に長い記事のために申し訳ありませんが、私はあなたが私を助けることを願ってこれ!

+0

クラスAのコメントプロパティを設定する必要はありませんが、それでもバインドできます。ユーザーがコメントフィールドを埋めると、 'ClassA'オブジェクトは必要なすべての情報を保持します。 – Sidewinder94

+0

' PropertyChange'イベントを使用しないと意味しますか? – SerpentSolide

+0

バウンドコントロールがプロパティを変更する唯一のコントロールならば、 'PropertyChanged'イベントは必要ありません。このイベントは、変更されたこのプロパティに依存する他のオブジェクトを通知するために使用されます。 – Sidewinder94

答えて

0

これは予想よりも単純な方法でしたが、私は無用なコードを掘り下げていました! 私はObservableCollectionPropertyChangeイベントに関するすべてのコードを取り除いています。

私の最終的に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>(); 
    } 
} 

そして、私の最後のClickイベント:

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

はSidewinder94 @ありがとうございます!

関連する問題