2010-03-30 7 views
0

나는 두 사람의 간단한 Silverlight 대화방을 만드는 작업을했습니다. 내 컨트롤이 너무 오래 있다면 Silverlight 채팅 WrapPanel 충돌/버그

  • 텍스트 줄 바꿈합니다

    1. 스크롤 다음과 같은 요구 사항을 준수해야합니다
    2. 새 항목/메시지는

    지금보기에 그 항목을 스크롤합니다 추가 될 때 나는 이러한 요구 사항을 충족하기 위해 성공적으로 usercontrol을 만들었지 만 가능한 버그/충돌에 직면했습니다. 나는 버그를 수정하거나 스크롤 가능한 채팅 컨트롤을 만드는 다른 접근법을 찾고있다.

    다음은 내가 사용 해본 코드입니다. 채팅 창에 대한 XAML부터 시작하겠습니다.

    <ListBox x:Name="lbChatHistory" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Disabled" > 
        <ListBox.ItemTemplate> 
        <DataTemplate> 
         <Grid Background="Beige"> 
         <Grid.ColumnDefinitions> 
            <ColumnDefinition Width="70"></ColumnDefinition> 
         <ColumnDefinition Width="Auto"></ColumnDefinition> 
         </Grid.ColumnDefinitions> 
         <TextBlock x:Name="lblPlayer" Foreground="{Binding ForeColor}" Text="{Binding Player}" Grid.Column="0"></TextBlock> 
         <ContentPresenter Grid.Column="1" Width="200" Content="{Binding Message}" /> 
        </Grid> 
        </DataTemplate> 
    </ListBox.ItemTemplate> 
    </ListBox> 
    

    아이디어는 목록 상자에 새 항목을 추가하는 것입니다. Item (XAML에 레이아웃 된대로)은 간단한 2 열 그리드입니다. 사용자 이름에 대해 하나의 열과 메시지에 대해 하나의 열.

    이제 ListBox에 추가하는 "항목"이 사용자 지정 클래스입니다. XAML 내에서 바인딩을 사용하는 세 가지 속성 (Player, ForeColor 및 Message)이 있습니다.

    플레이어은 표시 할 현재 사용자의 문자열입니다.

    ForeColor은 전경색 선호도입니다. 그것은 메시지의 차이를 구별하는 데 도움이됩니다.

    메시지WrapPanel입니다. 프로그래밍 방식으로 공백에 제공된 문자열을 각 단어에 나누십시오. 그런 다음 각 단어에 대해, 나는 여기에 WrapPanel

    에 새 TextBlock의 요소를 추가 사용자 정의 클래스입니다.

    public class ChatMessage :DependencyObject, INotifyPropertyChanged 
    { 
        public event PropertyChangedEventHandler PropertyChanged; 
    
        public static DependencyProperty PlayerProperty = DependencyProperty.Register("Player", typeof(string), typeof(ChatMessage), 
                             new PropertyMetadata(
                              new PropertyChangedCallback(OnPlayerPropertyChanged))); 
    
        public static DependencyProperty MessageProperty = DependencyProperty.Register("Message", typeof(WrapPanel), typeof(ChatMessage), 
                             new PropertyMetadata(
                              new PropertyChangedCallback(OnMessagePropertyChanged))); 
    
        public static DependencyProperty ForeColorProperty = DependencyProperty.Register("ForeColor", typeof(SolidColorBrush), typeof(ChatMessage), 
                             new PropertyMetadata(
                              new PropertyChangedCallback(OnForeColorPropertyChanged))); 
    
        private static void OnForeColorPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        { 
         ChatMessage c = d as ChatMessage; 
         c.ForeColor = (SolidColorBrush) e.NewValue; 
        } 
    
        public ChatMessage() 
        { 
         Message = new WrapPanel(); 
         ForeColor = new SolidColorBrush(Colors.White); 
        } 
    
        private static void OnMessagePropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        { 
         ChatMessage c = d as ChatMessage; 
         c.Message = (WrapPanel) e.NewValue; 
        } 
    
        private static void OnPlayerPropertyChanged(DependencyObject d, DependencyPropertyChangedEventArgs e) 
        { 
         ChatMessage c = d as ChatMessage; 
         c.Player = e.NewValue.ToString(); 
        } 
    
        public SolidColorBrush ForeColor 
        { 
         get { return (SolidColorBrush) GetValue(ForeColorProperty); } 
         set 
         { 
          SetValue(ForeColorProperty, value); 
          if(PropertyChanged != null) 
           PropertyChanged(this, new PropertyChangedEventArgs("ForeColor")); 
         } 
        } 
    
        public string Player 
        { 
         get { return (string) GetValue(PlayerProperty); } 
         set 
         { 
          SetValue(PlayerProperty, value); 
          if (PropertyChanged != null) 
           PropertyChanged(this, new PropertyChangedEventArgs("Player")); 
         } 
        } 
    
        public WrapPanel Message 
        { 
         get { return (WrapPanel) GetValue(MessageProperty); } 
         set 
         { 
          SetValue(MessageProperty, value); 
          if (PropertyChanged != null) 
           PropertyChanged(this, new PropertyChangedEventArgs("Message")); 
         } 
        } 
    } 
    

    마지막으로 ListBox에 항목을 추가합니다. 간단한 방법이 있습니다. 위의 ChatMessage 클래스를 매개 변수로 사용합니다.

    public void AddChatItem(ChatMessage msg) 
        { 
         lbChatHistory.Items.Add(msg); 
         lbChatHistory.ScrollIntoView(msg); 
        } 
    

    이제 테스트 해 보았습니다. 내가 얻는 문제는 스크롤 막대를 사용할 때입니다. 측면 스크롤 막대 또는 화살표 키를 사용하여 아래로 스크롤 할 수 있지만 Silverlight가 위로 스크롤하면 스크롤이 끊어집니다. FireBug는 ManagedRuntimeError # 4004XamlParseException으로 반환합니다.

    나는이 제어 작업을하는 것에 가까워서 맛볼 수있다! 내가해야 할 일이나 변경해야 할 일에 대한 생각? 제가 택한 것보다 더 좋은 접근법이 있습니까?

    미리 감사드립니다.

    UPDATE는

    전에서 ScrollViewer와 ItemsControl을 대신 ListBox 컨트롤을 사용하여 대체 솔루션을 발견했습니다. 대부분 안정적입니다.

  • 답변

    0

    ListBox 컨트롤 대신 ScrollViewer와 ItemsControl을 사용하는 대안 솔루션을 발견했습니다. 대부분 안정적입니다.

    여기에 지금 사용하는 XAML이 있습니다.

    <ScrollViewer x:Name="lbChatHistoryScroller"> 
            <ItemsControl x:Name="lbChatHistory" Grid.Row="0" Grid.Column="0" Grid.ColumnSpan="2" ScrollViewer.VerticalScrollBarVisibility="Visible" ScrollViewer.HorizontalScrollBarVisibility="Disabled"> 
             <ItemsControl.ItemTemplate> 
              <DataTemplate> 
               <Grid Background="Beige"> 
                <Grid.ColumnDefinitions> 
                 <ColumnDefinition Width="70"></ColumnDefinition> 
                 <ColumnDefinition Width="Auto"></ColumnDefinition> 
                </Grid.ColumnDefinitions> 
                <TextBlock x:Name="lblPlayer" Foreground="{Binding ForeColor}" Text="{Binding Player}" Grid.Column="0"></TextBlock> 
                <ContentPresenter Grid.Column="1" Width="1750" Content="{Binding Message}"> 
                </ContentPresenter> 
               </Grid> 
              </DataTemplate> 
             </ItemsControl.ItemTemplate> 
            </ItemsControl> 
           </ScrollViewer>