none
ListView 에서 RIchTextBlock을 DataTemplate으로 사용할때 질문 RRS feed

  • 질문

  • ListView에서 각 컬럼마다 각기 다양한 모양을 주기 위하여 RichTextBlock을 사용하였습니다.

    RichTextBlock Loaded 함수에서 각 컬럼에서 로드될때마다 각각 상황에 따른 모양을 만들어 놓도록 코드를 넣었습니다.

    문제는

    ListView에서 스크롤이 될때마다 RichTextBlock 컬럼들의 모양이 계속 랜덤하게 변함니다.

    예를 들면

    1번 컬럼이 이미지 + 텍스트 조합이고

    3번 컬럼이 이미지 + 텍스트 + 이미지 조합이고

    7번 컬럼이 텍스트 조합이라고 하면은

    스크롤 할떄마다 1번컬럼 모양새가 1번이 되었다가 3번이 되었다가 7번이 되었다가 아주 랜덤하게 나타납니다.

    제가 잘못 코드를 넣은 걸까요? 무엇 때문에 이런 현상이 나오는건지 이유를 도저히 모르겠습니다.

    다른방법이 있다면 알려주심 감사하겠습니다.

    • 이동됨 Jina Lee 2012년 10월 23일 화요일 오전 5:48 (이전 위치:Windows 스토어 앱)
    2012년 9월 25일 화요일 오전 10:06

답변

  • #region MyProperty /// <summary> /// Gets or sets the MyProperty possible Value of the int object./// </summary> publicintMyProperty  {      get { return (int)GetValue(MyPropertyProperty); }      set { SetValue(MyPropertyPropertyvalue); }  }  /// <summary> /// Identifies the MyProperty dependency property./// </summary> publicstaticreadonlyDependencyPropertyMyPropertyProperty =              DependencyProperty.Register(                   "MyProperty",                    typeof(int),                    typeof(ChatLogItemView),                    newPropertyMetadata(OnMyPropertyPropertyChanged));  /// <summary>/// MyPropertyProperty property changed handler. /// </summary>/// <param name="d">ChatLogItemView that changed its MyProperty.</param>/// <param name="e">DependencyPropertyChangedEventArgs.</param> privatestaticvoidOnMyPropertyPropertyChanged(DependencyObjectdDependencyPropertyChangedEventArgse)  {    ChatLogItemView_ChatLogItemView = dasChatLogItemView;    if (_ChatLogItemView!=null)    {  //여기다가 넣으시면 됩니다.   } }  #endregion MyProperty

    어이쿠 붙여넣으닌까 이렇게 나오는군용 ㅎㅎㅎㅎ 아무튼 Set에서 처리하지 마시고 DependencyProperty을 등록 할 때 PropertyMetadata을

    등록 할 수 있는데 여기에 다시 PropertyChangedCallback을 등록하게 되어 있습니다 거기서 원하시는 내용을 작성하시면 됩니다~

                     
    • 답변으로 표시됨 뽕빤쓰 2012년 10월 4일 목요일 오전 6:13
    2012년 10월 4일 목요일 오전 4:16

모든 응답

  • 안녕하십니까? 뽕빤쓰 님,
    Microsoft MSDN의 Forum 사이트를 방문해 주셔서 감사합니다.
     
    현재 문의 하신 ”ListView 에서 RIchTextBlock을 DataTemplate으로 사용할때 질문" 대해 답변을 드리겠습니다.

    제 생각에는 RichTextBox 를 이용하셔서 구현하시기 바랍니다.

    Silverlight 5에서는 서식 있는 텍스트를 표시하는 데 사용할 수 있는 RichTextBlock 컨트롤을 소개합니다.
    RichTextBox 는 단락, 하이퍼링크, 인라인 이미지 등의 다양한 콘텐츠를 표시하거나 편집할 수 있도록 하는 컨트롤입니다.

    제시해 드린 답변이 도움이 되었기를 바랍니다.
     
    답변이 문제 해결에 도움이 되었다면 답변으로 채택을 부탁드립니다.
    하지만 문제 해결이 되지 않아서 정확한 답변을 원하는 경우에는 문제의 정보를 더 자세하게 답변으로 제공해주시기 바랍니다.

    2012년 9월 25일 화요일 오전 11:46
  • 안녕하세요. 답변 달아주셔서 감사합니다.

    제가 현재 개발하고 있는거는 window 8  metro app을 개발중입니다.

    관련해서 답변을 주시면 감사하겠습니다.

    2012년 9월 26일 수요일 오전 1:31
  • Loaded가 되고 나서 RichTextBlock안에 있는 내용을 비워주고 있으신가요?

    스크롤을 내리게 되면 Virtualizing 이 일어나서 기존의 Item을 그대로 다시 사용합니다. 그렇기 때문에 아이템을 또 사용하게 된다고 생각 하시고 구현해 주셔야 합니다.

    안그러면 기존의 내용이 겹쳐서 보일수 있게 됩니다 ~_~

    2012년 9월 26일 수요일 오전 4:53
  • XAML에서 RichTextBlock 을 생성해 놓고 실제 내부 모양새는 Loaded 이벤트가 발생하였을때 생성해주고 있습니다.

    실제 XAML 에서는

    <RichTextBlock x:Name="textBlock" Loaded="RichTextBlockLoaded" />

    이렇게 이벤트를 넣어놓았고

    cs 파일에서는

    private void RichTextBlockLoaded(object sender, RoutedEventArgs e)

    {

    var blocks = ((RichTextBlock)sender).Blocks;

    Paragraph p = new Paragraph();

    .....  // Loaded되는 순서에 따라서 다르게 모양새를 만들어줌

    blocks.Add(p);

    }

    이런식으로 코드를 넣어왔습니다.

    문제는 스크롤을 하게 되면은 내용이 겹치는게 아니라 질문의 내용처럼 1번 아이템의 내용이 1번이 되었다가 3번이 되었다가 7번이 되었다가

    아주 랜덤하게 보여진다는 것입니다. 실제 ListView의 아이템 data 순서는 변한것이 없는데도 말입니다.

    2012년 9월 26일 수요일 오전 5:48
  • blocks.Add(p);을 호출하기전에 blocks.Clear()을 호출해주시고 한 번 해봐주시겠어용~_~?

    2012년 9월 26일 수요일 오전 6:55
  • 네 그렇게 해도 문제는 그대로 이네요 ㅠㅠ;

    2012년 9월 26일 수요일 오전 7:14
  • 으허허허 그렇다면 의심 되는건 Loaded 이벤트에서 처리하기 때문에 발생하는 문제가 아닐까 생각이 됩니다.

    예를 들어 하나의 RichTextBlock에 대해서 1,7,12번 데이타가 들어왔을 때 Virtualizing 때문에 3번의 Loaded 이벤트가 발생하게 될테데요. 그런데 이 때 Loaded 이벤트 발생하는 순서가 꼭 1,7,12번 순서로 들어온다는 보장이 없기 때문에 꼭 12번 데이타가 표시 되지 않을 수도 있을것 같습니당 ~_~

    2012년 9월 26일 수요일 오후 1:58
  • 그렇다면 어떻게 해야 표현을 할 수 있을까요?

    제가 원하는건 ListView의 아이템마다 RichTextView 내용을 각각 다르게 표현하고 싶은것인데

    어떤 방법이 좋을까요? ㅠㅠ

    2012년 9월 27일 목요일 오전 4:38
  • 머 하자고 한다면 current data가 12라고 했을 때, Loaded 이벤트에서 현재 set되는 data와 current data가 같은지를 체크해서 다르다면 pass 같으면 진행. 이렇게 처리하면 되지 않을까요?

    2012년 9월 27일 목요일 오전 4:41
  • 처음 로드 될떄는 Loaded 이벤트가 발생하지만 이후에 스크롤 시에는 Loaded 메소드가 발생하지 않습니다.

    DataTemplateSelector 만 계속 호출이 되지요.

    List<T> 가 10개가 있다고 한다면  Loaded 메소드에서는 10개중 하나의 데이터를 가져와서(이미 사용한 데이터는 가져오지 않습니다.) 파싱하여 RichTextBlock로 만들어주고  있습니다.

    ListView가 만들어진 상태에서는 이미 10개의 Item들이 만들어져 있고 아이템의 모양새가 갖추어져있겠지요.

    다만 스크롤 시에는 이미 만들어 놓은 아이템들(아이폰으로 얘기하면 테이블뷰의 셀)이 재사용되어서 사용되는데 DataTemplateSelector에서 바인딩되어 있는 TextBlock, Button과 같은 녀석들은 그대로 가져오게 되는데 유독 Loaded이벤트에서 동적으로 생성되는 RichTextBlock녀석들만 위와 같은 현상이 나옵니다.

    제 생각에는 Loaded 메소드에서 동적으로 RichTextBlock의 모양새를 만들어주기 보다는 DataTemplateSelector가 호출될때 마다 RichTextBlock의 모양새를 만들어줘야 될거 같은데 DataTemplateSeletor를 통해서 RichTextBlock의 객체에 접근하는 방법을 모르겠더군요.


    • 편집됨 뽕빤쓰 2012년 9월 27일 목요일 오전 7:13
    2012년 9월 27일 목요일 오전 7:12
  • 답변에서 이야기 해주신것처럼 Loaded가 아이템당 한 번 뿐이 발생하지 않는다면 위에 문제는 너무나 당연한 이야기 입니다. 처음 각각의 객체가 만들어져서 Loaded 이벤트에서 만들어진 아이템들이 Data을 다시 받고 있지 않고 기존에 만들어진 객체들이 단순 Virtualizing을 통해서 재배치만 된 상황인것 같습니다.

    그렇다면 이런 경우에는 조금 쉽게 풀어 갈려면 AAA라는 UserControl 혹은 CustomControl을 만들고 해당 Control에게 AAAData 라는 Dependency Property을 만들어서 노출시켜주고, DataTemplate 에는 AAAControl을 지정해주고 만들어 놓은 AAAData라는 DependencyProperty 에다가 반영 시킬려는 Data를 Binding 시켜주신 다음에 AAAData가 변경이 될 때 Loaded에서 했던 작업을 해주시면 될 것 같습니다 ~_~

    2012년 9월 27일 목요일 오후 1:21
  • 명절이라 답변을 이제 봤네요^^; 매번 답변 달아주셔서 감사합니다.

    말씀해주신데로 property로 만들어서 set이 되는 시점에 하고자 하는 코드를 넣었으나 아무런 반응이 없었네요 ㅠㅠ

    혹시나 set이 안되는가 싶었지만 바인딩은 잘되어서 값이 정상적으로 노출되는 것을 확인하였습니다

    후아.... 울고 싶군요 ㅋㅋ;;

    2012년 10월 4일 목요일 오전 1:41
  • #region MyProperty /// <summary> /// Gets or sets the MyProperty possible Value of the int object./// </summary> publicintMyProperty  {      get { return (int)GetValue(MyPropertyProperty); }      set { SetValue(MyPropertyPropertyvalue); }  }  /// <summary> /// Identifies the MyProperty dependency property./// </summary> publicstaticreadonlyDependencyPropertyMyPropertyProperty =              DependencyProperty.Register(                   "MyProperty",                    typeof(int),                    typeof(ChatLogItemView),                    newPropertyMetadata(OnMyPropertyPropertyChanged));  /// <summary>/// MyPropertyProperty property changed handler. /// </summary>/// <param name="d">ChatLogItemView that changed its MyProperty.</param>/// <param name="e">DependencyPropertyChangedEventArgs.</param> privatestaticvoidOnMyPropertyPropertyChanged(DependencyObjectdDependencyPropertyChangedEventArgse)  {    ChatLogItemView_ChatLogItemView = dasChatLogItemView;    if (_ChatLogItemView!=null)    {  //여기다가 넣으시면 됩니다.   } }  #endregion MyProperty

    어이쿠 붙여넣으닌까 이렇게 나오는군용 ㅎㅎㅎㅎ 아무튼 Set에서 처리하지 마시고 DependencyProperty을 등록 할 때 PropertyMetadata을

    등록 할 수 있는데 여기에 다시 PropertyChangedCallback을 등록하게 되어 있습니다 거기서 원하시는 내용을 작성하시면 됩니다~

                     
    • 답변으로 표시됨 뽕빤쓰 2012년 10월 4일 목요일 오전 6:13
    2012년 10월 4일 목요일 오전 4:16
  • 아 ㅎㅎㅎㅎㅎ 해결됬네요 ㅋㅋ 몇일동안의 삽질이 이렇게 해결되다니... ㅠㅠ;

    친절하게 답변 달아주셔서 감사합니다^^ 

    2012년 10월 4일 목요일 오전 6:13