模仿WP7的短信列表效果,先来看下效果图:
Metro样式确实看着很舒服。下面来说下具体实现过程。
本来想写一个自定义控件,但是觉得没有用户控件来得方便,遂改成了用户控件,那首先新建一个用户控件。
起个名字:MetroListBoxItem。
前台的代码:
<Grid Margin="5 3 5 3" HorizontalAlignment="Left">
<Grid.RowDefinitions>
<RowDefinition Height="10*"/>
<RowDefinition/>
<RowDefinition Height="10*"/>
</Grid.RowDefinitions>
<Rectangle x:Name="rectTop" Grid.Row="0" Height="10" Width="10" HorizontalAlignment="Left">
<Rectangle.RenderTransform>
<TransformGroup>
<SkewTransform AngleY="45"/>
<TranslateTransform Y="5"/>
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
<StackPanel x:Name="panel" Grid.Row="1" Orientation="Vertical" Panel.ZIndex="1">
<TextBlock MaxWidth="200" x:Name="txtContent" Margin="6 3 3 3" Foreground="White" FontSize="13" TextWrapping="Wrap"/>
<TextBlock x:Name="txtTime" Margin="3 0 3 3" Foreground="WhiteSmoke" HorizontalAlignment="Right"/>
</StackPanel>
<Rectangle Visibility="Collapsed" x:Name="rectBottom" Grid.Row="2" Height="10" Width="10" HorizontalAlignment="Right">
<Rectangle.RenderTransform>
<TransformGroup>
<SkewTransform AngleY="45"/>
<TranslateTransform Y="-15"/>
</TransformGroup>
</Rectangle.RenderTransform>
</Rectangle>
</Grid>
由于不像Iphone那样的短信列表,所以不需要很多的素材,实现起来很方便。
一个Grid,里面分为三行,上下两行分别放置两个气泡箭头,中间那层就放置内容。看下后台代码:
public bool IsLeft { get { return (bool)GetValue(IsLeftProperty); } set { SetValue(IsLeftProperty, value); } } // Using a DependencyProperty as the backing store for IsLeft. This enables animation, styling, binding, etc... public static readonly DependencyProperty IsLeftProperty = DependencyProperty.Register("IsLeft", typeof(bool), typeof(MetroListBoxItem), new PropertyMetadata(true, (s, e) => OnChanged(s, e))); private static void OnChanged(DependencyObject s, DependencyPropertyChangedEventArgs e) { var item = s as MetroListBoxItem; if ((bool)e.NewValue == true) { item.rectTop.Visibility = Visibility.Visible; item.rectBottom.Visibility = Visibility.Collapsed; } else { item.rectTop.Visibility = Visibility.Collapsed; item.rectBottom.Visibility = Visibility.Visible; item.HorizontalAlignment = HorizontalAlignment.Right; } } public string Text { get { return txtContent.Text; } set { txtTime.Text = DateTime.Now.ToString("HH:mm:ss"); txtContent.Text = value; } } public new Brush Background { set { rectTop.Fill = value; rectBottom.Fill = value; panel.Background = value; } }
先是声明了一个依赖属性:IsLeft,用来标识是在左边显示还是在右边。
然后是一个回调函数,当属性改变后做出相应的外观改变。也就是当显示为左边则把下层的气泡箭头隐藏掉,反之。
然后是两个属性,用来显示内容,和设置背景色。
接下来是主窗体前台代码:
<Grid>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="348*" />
<ColumnDefinition Width="155*" />
</Grid.ColumnDefinitions>
<Grid.RowDefinitions>
<RowDefinition Height="280*" />
<RowDefinition Height="35*" />
</Grid.RowDefinitions>
<ListBox Name="listBox" Grid.ColumnSpan="2">
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
</ListBox>
<Button Content="Left" Grid.Row="1" Height="23" Margin="3" Name="btnAddLeft" HorizontalAlignment="Left" Width="75" Grid.Column="1" Click="btnAddLeft_Click" />
<Button Content="Right" Grid.Row="1" Height="23" Margin="3" Name="btnAddRight" HorizontalAlignment="Right" Width="75" Grid.Column="1" Click="btnAddRight_Click" />
<TextBox Grid.Row="1" Height="23" Margin="5" Name="txtContent" Width="370" />
</Grid>
里面最主要的代码就是:
<ListBox.ItemContainerStyle>
<Style TargetType="ListBoxItem">
<Setter Property="HorizontalContentAlignment" Value="Stretch"/>
</Style>
</ListBox.ItemContainerStyle>
这个能调整布局。
然后是后台:
private void btnAddLeft_Click(object sender, RoutedEventArgs e) { items.Add(new MetroListBoxItem { Background = new SolidColorBrush { Color = Color.FromArgb(255, 30, 175, 45) }, Text = txtContent.Text, IsLeft = true }); listBox.ItemsSource = items; ToBottom(); } private void btnAddRight_Click(object sender, RoutedEventArgs e) { items.Add(new MetroListBoxItem { Background = new SolidColorBrush { Color = Color.FromArgb(255, 25, 130, 45) }, Text = txtContent.Text, IsLeft = false }); listBox.ItemsSource = items; ToBottom(); } void ToBottom() { var sv = FindChildOfType<ScrollViewer>(listBox); sv.ScrollToEnd(); }
两个按钮事件中动态的设置左右显示和背景色。
下面的方法是滚动到最下面,就像QQ消息框。
OK,还可以继续完善,比如为向下滚动添加动画效果...