Silverlight Chat WrapPanel崩溃/ Bug

时间:2010-03-30 18:14:20

标签: silverlight wrappanel chatroom

我被赋予了为两个人创建一个简单的Silverlight聊天框的任务。我的控制必须遵守以下要求

  1. 滚动
  2. 如果篇幅太长,文字必须换行
  3. 添加新项目/消息时,必须将该项目滚动到视图
  4. 现在我已经成功地完成了一个用户控制来满足这些要求,但是我遇到了一个可能的错误/崩溃,我无法解决这个问题。我正在寻找修复bug或者创建可滚动聊天控件的不同方法。

    这是我一直在使用的代码。我们将从我的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>
    

    我们的想法是在列表框中添加一个新项目。项目(如XAML中所示)是一个简单的2列网格。用户名的一列,以及邮件的一列。

    现在我添加到ListBox的“项目”是一个自定义类。它有三个属性(Player,ForeColor和Message),我在XAML中使用绑定

    播放器是要显示的当前用户的字符串。

    ForeColor 只是前景色偏好。它有助于区分消息之间的区别。

    消息 WrapPanel 。我以编程方式打破白色空间上提供的字符串每个单词。然后,对于每个单词,我将 TextBlock 元素添加到 WrapPanel

    这是自定义类。

    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使用 XamlParseException 返回 ManagedRuntimeError#4004

    我很接近控制工作,我可以品尝它!关于我应该做什么或改变什么的想法?有没有比我采取的方法更好的方法?

    提前致谢。

    更新

    我找到了一个使用ScrollViewer和ItemsControl而不是ListBox控件的替代解决方案。在大多数情况下,它是稳定的。

1 个答案:

答案 0 :(得分:0)

我找到了一个使用ScrollViewer和ItemsControl而不是ListBox控件的替代解决方案。在大多数情况下,它是稳定的。

这是我现在使用的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>