模仿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,还可以继续完善,比如为向下滚动添加动画效果...