Silverlight 聊天 WrapPanel 崩溃/错误
我的任务是为两个人创建一个简单的 Silverlight 聊天框。我的控件必须遵守以下要求
- 可滚动
- 文本如果太长则必须换行
- 当添加新项目/消息时,它必须将该项目滚动到视图中
现在我已经成功制作了一个用户控件来满足这些要求,但我遇到了一个可能的错误/崩溃,我一生都无法修复。我正在寻找修复该错误的方法,或者寻找创建可滚动聊天控件的不同方法。
这是我一直在使用的代码。我们将从聊天窗口的 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 列网格。一列用于用户名,一列用于消息。
现在,我添加到列表框的“项目”是一个自定义类。它具有三个属性(Player、ForeColor 和 Message),我在 XAML 中使用它们进行绑定
Player 是要显示的当前用户的字符串。
ForeColor 只是前景色首选项。它有助于区分消息之间的差异。
Message 是一个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" ) );
}
}
}
最后,我将我的项目添加到列表框中。这是简单的方法。它采用上面的 ChatMessage 类作为参数
public void AddChatItem( ChatMessage msg )
{
lbChatHistory.Items.Add( msg );
lbChatHistory.ScrollIntoView( msg );
}
现在我已经测试了它并且一切正常。我遇到的问题是当我使用滚动条时。您可以使用侧面滚动条或箭头键向下滚动,但向上滚动时 Silverlight 会崩溃。 FireBug 返回一个带有 XamlParseException 的 ManagedRuntimeError #4004。
我已经非常接近让这个控制起作用了,我可以尝到它的味道!有什么想法我应该做什么或改变吗?有没有比我所采取的方法更好的方法?
提前致谢。
更新
我找到了一种使用 ScrollViewer 和 ItemsControl 而不是 ListBox 控件的替代解决方案。大多数情况下它是稳定的。
I've been given the task to create a simple Silverlight chat box for two people. My control must adhere to the following requirements
- Scrollable
- Text must wrap if it's too long
- When a new item / message is added it must scroll that item into view
Now I've successfully made a usercontrol to meet these requirements, but I've run into a possible bug / crash that I can't for the life of me fix. I'm looking for either a fix to the bug, or a different approach to creating a scrollable chat control.
Here's the code I've been using. We'll start with my XAML for the chat window
<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>
The idea is to add a new Item to the listbox. The Item (as layed out in the XAML) is a simple 2 column grid. One column for the username, and one column for the message.
Now the "items" that I add to the ListBox is a custom class. It has three properties (Player, ForeColor, and Message) that I using binding on within my XAML
Player is a string of the current user to display.
ForeColor is just a foreground color preference. It helps distinguish the difference between messages.
Message is a WrapPanel. I programmatically break the supplied string on the white space for each word. Then for each word, I add a new TextBlock element to the WrapPanel
Here is the custom class.
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" ) );
}
}
}
Lastly I add my items to the ListBox. Here's the simple method. It takes the above ChatMessage class as a parameter
public void AddChatItem( ChatMessage msg )
{
lbChatHistory.Items.Add( msg );
lbChatHistory.ScrollIntoView( msg );
}
Now I've tested this and it all works. The problem I'm getting is when I use the scroll bar. You can scroll down using the side scroll bar or arrow keys, but when you scroll up Silverlight crashes. FireBug returns a ManagedRuntimeError #4004 with a XamlParseException.
I'm soo close to having this control work, I can taste it! Any thoughts on what I should do or change? Is there a better approach than the one I've taken?
Thanks in advance.
UPDATE
I've found an alternative solution using a ScrollViewer and an ItemsControl instead of a ListBox control. For the most part it's stable.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
我找到了使用 ScrollViewer 和 ItemsControl 而不是 ListBox 控件的替代解决方案。大多数情况下它是稳定的。
这是我现在使用的 XAML。
I've found an alternative solution using a ScrollViewer and an ItemsControl instead of a ListBox control. For the most part it's stable.
Here's the XAML I use now instead.