[UWP开发]UI模板(一)

[UWP开发]UI模板(一)

总结一些以前用过的界面框架,贴出来给新手参考。
先介绍一个用于文章的图文混排,具有列表的格式。

[UWP开发]UI模板(一)_第1张图片

左边为标题,文字内容。下面为一个List结构,包含标题和内容。右边为图片。

1 . Model

整体结构

public class ProductListItem
{
    public ProductListItem(string title, string content, List li, PageType frameType, Uri pic)
    {
        Title = title;  //标题
        Content = content;  //文本内容
        Li = li;  //列表
        FrameType = frameType;  //页面标记,定义为enum
        Pic = pic;  //图片路径
    }

    public string Title { get; set; }
    public string Content { get; set; }
    public PageType FrameType { get; set; }
    public List Li { get; set; }
    public Uri Pic { get; set; }
    public ImageSource Is
    {
        get
        {
            return new BitmapImage(Pic);
        }
    }
}

列表结构

public class TitleContent
{
    public TitleContent(string title, string content)
    {
        Title = title;
        Content = content;
    }

    public string Title { get; set; }
    public string Content { get; set; }
}

2 . ViewModel

class ProductListViewModel
{
    public List SelectedProductItems = new List();
    public List _ProductItems = null;

    public ProductListViewModel()
    {
        if (_ProductItems == null)
        {
            InitProductItems();
        }
    }

//所有的赋值操作
    public void InitProductItems()
    {
        var resourceLoader = ResourceLoader.GetForCurrentView();
        _ProductItems = new List();
        List Tc = new List();
        Tc.Add(new TitleContent("Universal Windows Application1", "Hello World!"));
        Tc.Add(new TitleContent("Universal Windows Application2", string.Empty));
        Tc.Add(new TitleContent("Universal Windows Application3", "Good!"));
        _ProductItems.Add(new ProductListItem("CSDN Blog", "http://blog.csdn.net/xiahn1a", Tc, PageType.ProductPage1, new Uri("ms-appx:///Assets/rocket.jpg")));
    }

//根据页面的标记,选出用于该页面的信息
    public void GetSelectedItem(PageType pt)
    {
        SelectedProductItems = _ProductItems.Where(i => i.FrameType == pt).ToList();
    }
}

3.View

xmlns:ValueConverters="using:MyApp.ValueConverters"

定义列表数据模板:

<Page.Resources>
    <ValueConverters:StringEmptyToVisibilityConverter x:Key="StringEmptyToVisibilityConverter"/>
    <DataTemplate x:Key="MainProductItemTemplate" x:DataType="local:TitleContent">
        <StackPanel>
            <Grid Margin="0,0,0,5">
                <Grid.ColumnDefinitions>
                    <ColumnDefinition Width="auto">ColumnDefinition>
                    <ColumnDefinition Width="*">ColumnDefinition>
                Grid.ColumnDefinitions>
                <SymbolIcon Grid.Column="0" Symbol="Accept" Foreground="#FF1ABC9C" />
                <TextBlock Grid.Column="1" Text="{x:Bind Title}" Margin="15,5,0,5" FontSize="16" TextWrapping="Wrap"/>
            Grid>
            <TextBlock Text="{x:Bind Content}" FontSize="16" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" TextWrapping="Wrap" Visibility="{x:Bind Content, Converter={StaticResource StringEmptyToVisibilityConverter}}" Margin="0,0,0,5"/>
        StackPanel>

    DataTemplate>
Page.Resources>

其中用到的Converter,意义在于设定部分可见性。此处定义为,如果字符串为空,则该部分不可见。这样使得模板在某部分信息缺失时也可用,不会影响排版。Converter定义如下:

namespace MyApp.ValueConverters
{
    public class StringEmptyToVisibilityConverter : IValueConverter
    {
        public object Convert(object value, Type targetType, object parameter, string language)
        {
            if (value == null)
                return Visibility.Collapsed;

            var result = (string)value;

            return result.Equals(string.Empty) ? Visibility.Collapsed : Visibility.Visible;
        }

        public object ConvertBack(object value, Type targetType, object parameter, string language)
        {
            throw new NotImplementedException();
        }
    }
}

定义左侧文字整体结构:

<Grid x:Name="Grid_Main" Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    "0,20,0,0">
        "Tb_Title" Text="{Binding Title}" FontSize="20" HorizontalAlignment="Center" Margin="0,0,0,0" VerticalAlignment="Top" Foreground="#FF1ABC9C" TextWrapping="Wrap" FontWeight="Normal"/>
        "Tb_Content" Text="{Binding Content}" FontSize="16" Margin="10,10,10,10" VerticalAlignment="Top" TextWrapping="Wrap" Visibility="{Binding Content, Converter={StaticResource StringEmptyToVisibilityConverter}}"/>
        "Lv_Main" ItemTemplate="{StaticResource MainProductItemTemplate}" HorizontalContentAlignment="Stretch" Style="{StaticResource ListViewStyle1}" ItemContainerStyle="{StaticResource TitleItemContainerStyle}" ItemsSource="{Binding Li}" Margin="10,0,10,0"/>
    
Grid>

其中对ListView的Style进行了修改,主要目的是删减多余的动画效果。代码过长且并不关键,不贴了。

对应的后台cs文件:

public sealed partial class ProductListView : Page
{
    public ProductListView()
    {
        this.InitializeComponent();
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
        DataContext = e.Parameter;
    }
}

界面定义时已进行数据绑定,此处只需DataContext = e.Parameter;赋值即可。

模板的引用方法:
在页面中定义一个Frame,后台代码中只需完成Frame跳转即可。

public sealed partial class ProductPage1 : Page
{
    private readonly ProductListViewModel _viewModel;

    public ProductPage1()
    {
        this.InitializeComponent();

        _viewModel = new ProductListViewModel();  //viewmodel
        _viewModel.GetSelectedItem(PageType.ProductPage1);  //选出用于本页使用的部分
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
        MainFrame.Navigate(typeof(ProductListView), _viewModel.SelectedProductItems[0]);  //跳转页面,传递数据
    }
}

如以后需要再使用该模板创建更多的实例,则在ViewModel中赋值,对_ProductItems加入更多信息。以PageType这个标记作为引用时的区分。引用不同数据时只需改PageType这一个参数即可。


已经完成了左边文字部分的模板定义。现在把图片加入进去,并且设置,当窗口过小时,排版规则从文字图片左右排布,变为上下排布。
再定义一个View:

<Grid Background="{ThemeResource ApplicationPageBackgroundThemeBrush}">
    <Grid.ColumnDefinitions>
        "1*">
        "1*">
    Grid.ColumnDefinitions>
    <Grid.RowDefinitions>
        "1*">
        "1*" MinHeight="300">
    Grid.RowDefinitions>
    <Grid x:Name="Grid1" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="0" Grid.RowSpan="1" Margin="5">
        <Frame x:Name="ProductFrame">Frame>
    Grid>
    <Grid x:Name="Grid2" Grid.Column="0" Grid.ColumnSpan="2" Grid.Row="1" Grid.RowSpan="1" Margin="5">
        <Grid.Background>
            "{Binding Is}" Stretch="Uniform"/>
        Grid.Background>
    Grid>

    
        
            
                
                    "{StaticResource LargeWindowSnapPoint}" />
                
                
                    <Setter Target="Grid1.(Grid.Column)" Value="0"/>
                    <Setter Target="Grid1.(Grid.ColumnSpan)" Value="1"/>
                    <Setter Target="Grid1.(Grid.Row)" Value="0"/>
                    <Setter Target="Grid1.(Grid.RowSpan)" Value="2"/>
                    <Setter Target="Grid2.(Grid.Column)" Value="1"/>
                    <Setter Target="Grid2.(Grid.ColumnSpan)" Value="1"/>
                    <Setter Target="Grid2.(Grid.Row)" Value="0"/>
                    <Setter Target="Grid2.(Grid.RowSpan)" Value="2"/>
                
            
        
    
Grid>

代码较多,但实际上只是定义了一个触发器。当窗口大小小于某个数值的时候,将Grid1和Grid2的左右排布变为上下排布。Grid1中的Frame即为上面定义的左侧文字部分。
后台代码与定义左侧部分时基本相同,代码如下:

public sealed partial class ProductListFullView : Page
{
    public ProductListFullView()
    {
        this.InitializeComponent();
    }

    protected override void OnNavigatedTo(NavigationEventArgs e)
    {
        base.OnNavigatedTo(e);
        DataContext = e.Parameter;
        ProductFrame.Navigate(typeof(ProductListView), e.Parameter);
    }
}

对于模板的修改,减少内容可以定义Visibility,利用Converter对于绑定参数内容,判断是否为空,决定可见性。
可根据实际情况进行修改,此类模板的定义基本大同小异。


代码通过Visual Studio 2017测试。
转载请注明出处。
请不要私信索要代码,代码都是从完整的工程中节选并简化的,写完这个文档以后我也没有留存。

你可能感兴趣的:(Windows应用商店)