提交 db759bf6 编写于 作者: A Anran Zhang

完善视频条目,横幅条目

上级 4a8a9a41
......@@ -17,9 +17,13 @@
<Compile Include="$(SolutionDir)\src\Shared\SharedAssemblyInfo.cs">
<Link>Properties\SharedAssemblyInfo.cs</Link>
</Compile>
<Compile Include="Controls\Bili\BannerItem.cs" />
<Compile Include="Controls\Bili\BannerView.xaml.cs">
<DependentUpon>BannerView.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\IconTextBlock.xaml.cs">
<DependentUpon>IconTextBlock.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\Layout\AdaptiveLayoutState.cs" />
<Compile Include="App.xaml.cs">
<DependentUpon>App.xaml</DependentUpon>
......@@ -47,6 +51,9 @@
<Compile Include="Controls\Bili\VideoView.xaml.cs">
<DependentUpon>VideoView.xaml</DependentUpon>
</Compile>
<Compile Include="Controls\Bili\UserAvatar.xaml.cs">
<DependentUpon>UserAvatar.xaml</DependentUpon>
</Compile>
<Compile Include="Pages\ChannelPage.xaml.cs">
<DependentUpon>ChannelPage.xaml</DependentUpon>
</Compile>
......@@ -181,6 +188,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\IconTextBlock.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\RootNavigationView.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
......@@ -193,6 +204,10 @@
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Controls\Bili\UserAvatar.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
</Page>
<Page Include="Pages\ChannelPage.xaml">
<SubType>Designer</SubType>
<Generator>MSBuild:Compile</Generator>
......@@ -269,11 +284,18 @@
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
<Page Include="Themes\Generic.xaml">
<Generator>MSBuild:Compile</Generator>
<SubType>Designer</SubType>
</Page>
</ItemGroup>
<ItemGroup>
<PackageReference Include="Fluent.Icons">
<Version>1.1.110</Version>
</PackageReference>
<PackageReference Include="HN.Controls.ImageEx.Uwp">
<Version>1.0.33</Version>
</PackageReference>
<PackageReference Include="Microsoft.CodeAnalysis.Metrics">
<Version>3.3.0</Version>
</PackageReference>
......@@ -289,6 +311,9 @@
<PackageReference Include="Newtonsoft.Json">
<Version>13.0.1</Version>
</PackageReference>
<PackageReference Include="Nito.AsyncEx.Tasks">
<Version>5.1.0</Version>
</PackageReference>
<PackageReference Include="StyleCop.Analyzers">
<Version>1.1.118</Version>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
......
// Copyright (c) Richasy. All rights reserved.
using System;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Input;
using Windows.UI.Xaml.Media;
namespace Richasy.Bili.App.Controls
{
/// <summary>
/// 横幅条目.
/// </summary>
public sealed class BannerItem : Control
{
/// <summary>
/// <see cref="Source"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty SourceProperty =
DependencyProperty.Register(nameof(Source), typeof(ImageSource), typeof(BannerItem), new PropertyMetadata(null));
/// <summary>
/// <see cref="Uri"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty UriProperty =
DependencyProperty.Register(nameof(Uri), typeof(string), typeof(BannerItem), new PropertyMetadata(null));
/// <summary>
/// <see cref="Title"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty TitleProperty =
DependencyProperty.Register(nameof(Title), typeof(string), typeof(BannerItem), new PropertyMetadata(null));
/// <summary>
/// Initializes a new instance of the <see cref="BannerItem"/> class.
/// </summary>
public BannerItem()
{
this.DefaultStyleKey = typeof(BannerItem);
}
/// <summary>
/// 图片源.
/// </summary>
public ImageSource Source
{
get { return (ImageSource)GetValue(SourceProperty); }
set { SetValue(SourceProperty, value); }
}
/// <summary>
/// 导航地址.
/// </summary>
public string Uri
{
get { return (string)GetValue(UriProperty); }
set { SetValue(UriProperty, value); }
}
/// <summary>
/// 标题.
/// </summary>
public string Title
{
get { return (string)GetValue(TitleProperty); }
set { SetValue(TitleProperty, value); }
}
/// <inheritdoc/>
protected async override void OnTapped(TappedRoutedEventArgs e)
{
if (!string.IsNullOrEmpty(Uri))
{
await Launcher.LaunchUriAsync(new Uri(Uri));
}
}
/// <inheritdoc/>
protected override void OnPointerPressed(PointerRoutedEventArgs e)
{
this.CapturePointer(e.Pointer);
VisualStateManager.GoToState(this, "PressedState", true);
}
/// <inheritdoc/>
protected override void OnPointerReleased(PointerRoutedEventArgs e)
{
VisualStateManager.GoToState(this, "NormalState", true);
this.ReleasePointerCapture(e.Pointer);
}
}
}
......@@ -39,14 +39,10 @@
<controls:ItemsRepeater x:Name="BannerRepeater" ItemsSource="{x:Bind ItemsSource, Mode=OneWay}">
<controls:ItemsRepeater.ItemTemplate>
<DataTemplate x:DataType="bilibili:Banner">
<Grid x:Name="ImageContainer" CornerRadius="{StaticResource ControlCornerRadius}">
<Image
AutomationProperties.Name="{x:Bind Title}"
MaxHeight="114"
Source="{x:Bind Image}"
Stretch="Uniform"
ToolTipService.ToolTip="{x:Bind Title}" />
</Grid>
<local:BannerItem
Title="{x:Bind Title}"
Source="{x:Bind Image}"
Uri="{x:Bind NavigateUri}" />
</DataTemplate>
</controls:ItemsRepeater.ItemTemplate>
<controls:ItemsRepeater.Layout>
......
// Copyright (c) Richasy. All rights reserved.
using System;
using Microsoft.UI.Xaml.Controls;
using Richasy.Bili.Models.BiliBili;
using Windows.System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
......@@ -87,5 +90,25 @@ namespace Richasy.Bili.App.Controls
{
CheckOffsetButtonStatus();
}
private async void OnBannerTappedAsync(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
var context = (sender as FrameworkElement).DataContext as Banner;
await Launcher.LaunchUriAsync(new System.Uri(context.NavigateUri));
}
private void OnBannerPointerPressed(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
var control = sender as Control;
control.CapturePointer(e.Pointer);
VisualStateManager.GoToState(control, "PressedState", true);
}
private void OnBannerPointerReleased(object sender, Windows.UI.Xaml.Input.PointerRoutedEventArgs e)
{
var control = sender as Control;
VisualStateManager.GoToState(sender as Control, "NormalState", true);
control.ReleasePointerCapture(e.Pointer);
}
}
}
<UserControl
x:Class="Richasy.Bili.App.Controls.UserAvatar"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:local="using:Richasy.Bili.App.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<Grid>
<muxc:PersonPicture
x:Name="PersonPicture"
Width="{x:Bind Width, Mode=OneWay}"
Height="{x:Bind Height, Mode=OneWay}"
BorderBrush="{x:Bind BorderBrush, Mode=OneWay}"
BorderThickness="{x:Bind BorderThickness, Mode=OneWay}"
DisplayName="{x:Bind UserName, Mode=OneWay}"
ToolTipService.ToolTip="{x:Bind UserName, Mode=OneWay}" />
</Grid>
</UserControl>
// Copyright (c) Richasy. All rights reserved.
using System;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
using Windows.UI.Xaml.Media.Imaging;
namespace Richasy.Bili.App.Controls
{
/// <summary>
/// 用户头像.
/// </summary>
public sealed partial class UserAvatar : UserControl
{
/// <summary>
/// <see cref="UserName"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty UserNameProperty =
DependencyProperty.Register(nameof(UserName), typeof(string), typeof(UserAvatar), new PropertyMetadata(string.Empty));
/// <summary>
/// <see cref="Avatar"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty AvatarProperty =
DependencyProperty.Register(nameof(Avatar), typeof(string), typeof(UserAvatar), new PropertyMetadata(string.Empty, new PropertyChangedCallback(OnAvatarChanged)));
/// <summary>
/// <see cref="DecodeSize"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty DecodeSizeProperty =
DependencyProperty.Register(nameof(DecodeSize), typeof(int), typeof(UserAvatar), new PropertyMetadata(50));
/// <summary>
/// Initializes a new instance of the <see cref="UserAvatar"/> class.
/// </summary>
public UserAvatar()
{
this.InitializeComponent();
}
/// <summary>
/// 用户名.
/// </summary>
public string UserName
{
get { return (string)GetValue(UserNameProperty); }
set { SetValue(UserNameProperty, value); }
}
/// <summary>
/// 头像.
/// </summary>
public string Avatar
{
get { return (string)GetValue(AvatarProperty); }
set { SetValue(AvatarProperty, value); }
}
/// <summary>
/// 解析图像的大小.
/// </summary>
public int DecodeSize
{
get { return (int)GetValue(DecodeSizeProperty); }
set { SetValue(DecodeSizeProperty, value); }
}
private static void OnAvatarChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = d as UserAvatar;
if (e.NewValue is string url && !string.IsNullOrEmpty(url))
{
instance.PersonPicture.ProfilePicture = new BitmapImage(new Uri(url)) { DecodePixelWidth = instance.DecodeSize };
}
}
}
}
......@@ -3,15 +3,26 @@
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:hn="using:HN.Controls"
xmlns:icons="using:Fluent.Icons"
xmlns:local="using:Richasy.Bili.App.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<UserControl.Resources>
<Style TargetType="local:IconTextBlock">
<Setter Property="Spacing" Value="4" />
<Setter Property="IconFontSize" Value="12" />
<Setter Property="FontSize" Value="12" />
</Style>
</UserControl.Resources>
<Grid
AutomationProperties.Name="{x:Bind ViewModel.Title, Mode=OneWay}"
Background="{ThemeResource CardBackgroundFillColorDefault}"
Background="{ThemeResource CardBackgroundFillColorDefaultBrush}"
BorderBrush="{ThemeResource CardStrokeColorDefaultBrush}"
BorderThickness="1"
CornerRadius="{ThemeResource OverlayCornerRadius}"
......@@ -31,30 +42,66 @@
<VisualState x:Name="VerticalState" />
<VisualState x:Name="HorizontalState">
<VisualState.Setters>
<Setter Target="CoverContainer.VerticalAlignment" Value="Center" />
<Setter Target="CoverContainer.VerticalAlignment" Value="Stretch" />
<Setter Target="CoverContainer.Height" Value="Auto" />
<Setter Target="CoverContainer.Width" Value="160" />
<Setter Target="CoverContainer.Margin" Value="8" />
<Setter Target="CoverContainer.CornerRadius" Value="{StaticResource ControlCornerRadius}" />
<Setter Target="ContentContainer.(Grid.Row)" Value="0" />
<Setter Target="ContentContainer.(Grid.Column)" Value="1" />
<Setter Target="ContentContainer.Padding" Value="8" />
<Setter Target="Row1.Height" Value="*" />
<Setter Target="Row2.Height" Value="Auto" />
<Setter Target="Column1.Width" Value="Auto" />
<Setter Target="Column2.Width" Value="*" />
<Setter Target="SingleAvatar.Visibility" Value="Collapsed" />
<Setter Target="InlineAvatar.Visibility" Value="Visible" />
<Setter Target="ContentRow1.Height" Value="*" />
<Setter Target="ContentRow2.Height" Value="Auto" />
<Setter Target="InlineUserContainer.(Grid.Row)" Value="1" />
<Setter Target="TitleBlock.(Grid.Row)" Value="0" />
</VisualState.Setters>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Grid x:Name="CoverContainer" Height="124">
<Image
<Grid
x:Name="CoverContainer"
Height="124"
VerticalAlignment="Stretch">
<hn:ImageEx
x:Name="CoverImage"
ImageFailed="CoverImage_ImageFailed"
LazyLoadingEnabled="True"
RetryCount="2"
RetryDelay="0:0:5"
Source="{x:Bind ViewModel.CoverUrl, Mode=OneWay}"
Stretch="UniformToFill" />
Stretch="UniformToFill">
<hn:ImageEx.LoadingTemplate>
<DataTemplate>
<Grid>
<muxc:ProgressRing
Style="{StaticResource PageProgressRingStyle}"
Width="28"
Height="28" />
</Grid>
</DataTemplate>
</hn:ImageEx.LoadingTemplate>
<hn:ImageEx.FailedTemplate>
<DataTemplate>
<Grid Background="{ThemeResource SystemControlForegroundBaseMediumBrush}" Opacity="0.5">
<icons:FluentIconElement
HorizontalAlignment="Center"
VerticalAlignment="Center"
Foreground="{ThemeResource SystemControlForegroundBaseMediumBrush}"
Symbol="Image28Filled" />
</Grid>
</DataTemplate>
</hn:ImageEx.FailedTemplate>
</hn:ImageEx>
<Grid
Margin="8,0,0,12"
Margin="8,0,0,8"
Padding="8,4"
HorizontalAlignment="Left"
VerticalAlignment="Bottom"
......@@ -65,34 +112,88 @@
</Grid>
</Grid>
<Grid
x:Name="SingleAvatar"
Margin="0,0,12,-18"
HorizontalAlignment="Right"
VerticalAlignment="Bottom">
<Ellipse
Width="40"
Height="40"
Fill="{ThemeResource CardBackgroundFillColorDefault}" />
<local:UserAvatar
Width="36"
Height="36"
HorizontalAlignment="Center"
VerticalAlignment="Center"
Avatar="{x:Bind ViewModel.PublisherAvatar}"
UserName="{x:Bind ViewModel.PublisherName}" />
</Grid>
<Grid
x:Name="ContentContainer"
Grid.Row="1"
Padding="12,8"
RowSpacing="8">
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
<RowDefinition x:Name="ContentRow1" Height="Auto" />
<RowDefinition x:Name="ContentRow2" Height="*" />
<RowDefinition Height="Auto" />
</Grid.RowDefinitions>
<StackPanel x:Name="InlineUserContainer" Orientation="Horizontal">
<local:UserAvatar
x:Name="InlineAvatar"
Width="24"
Height="24"
Margin="0,0,8,0"
VerticalAlignment="Center"
Visibility="Collapsed"
Avatar="{x:Bind ViewModel.PublisherAvatar}"
UserName="{x:Bind ViewModel.PublisherName}" />
<TextBlock
Style="{StaticResource CaptionTextBlockStyle}"
VerticalAlignment="Center"
Opacity="0.6"
Text="{x:Bind ViewModel.PublisherName, Mode=OneWay}" />
</StackPanel>
<TextBlock
Style="{StaticResource CaptionTextBlockStyle}"
Opacity="0.6"
Text="{x:Bind ViewModel.PublisherName, Mode=OneWay}" />
<TextBlock
x:Name="TitleBlock"
Grid.Row="1"
VerticalAlignment="Top"
MaxLines="2"
Text="{x:Bind ViewModel.Title, Mode=OneWay}"
TextTrimming="CharacterEllipsis"
TextWrapping="Wrap"
ToolTipService.ToolTip="{x:Bind ViewModel.Title, Mode=OneWay}" />
<TextBlock
x:Name="DescriptionBlock"
Style="{StaticResource CaptionTextBlockStyle}"
TextWrapping="Wrap">
<ToolTipService.ToolTip>
<ToolTip Content="{x:Bind ViewModel.Title, Mode=OneWay}" IsEnabled="{x:Bind TitleBlock.IsTextTrimmed, Mode=OneWay}" />
</ToolTipService.ToolTip>
</TextBlock>
<StackPanel
Grid.Row="2"
Opacity="0.6"
TextTrimming="CharacterEllipsis" />
Orientation="Horizontal"
Spacing="12">
<local:IconTextBlock
Opacity="0.6"
Symbol="PlayCircle16Filled"
Text="{x:Bind ViewModel.PlayCount, Mode=OneWay}"
Visibility="{x:Bind IsShowPlayCount, Mode=OneWay}" />
<local:IconTextBlock
Opacity="0.6"
Symbol="SlideText16Filled"
Text="{x:Bind ViewModel.DanmakuCount, Mode=OneWay}"
Visibility="{x:Bind IsShowDanmakuCount, Mode=OneWay}" />
<local:IconTextBlock
Opacity="0.6"
Symbol="ThumbLike16Filled"
Text="{x:Bind ViewModel.LikeCount, Mode=OneWay}"
Visibility="{x:Bind IsShowLikeCount, Mode=OneWay}" />
<local:IconTextBlock
Opacity="0.6"
Symbol="Comment16Filled"
Text="{x:Bind ViewModel.ReplyCount, Mode=OneWay}"
Visibility="{x:Bind IsShowReplayCount, Mode=OneWay}" />
</StackPanel>
</Grid>
</Grid>
</UserControl>
// Copyright (c) Richasy. All rights reserved.
using HN.Controls;
using Richasy.Bili.ViewModels.Uwp;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
......@@ -23,6 +24,36 @@ namespace Richasy.Bili.App.Controls
public static readonly DependencyProperty OrientationProperty =
DependencyProperty.Register(nameof(Orientation), typeof(Orientation), typeof(VideoItem), new PropertyMetadata(default(Orientation), new PropertyChangedCallback(OnOrientationChanged)));
/// <summary>
/// <see cref="IsShowPublishDateTime"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty IsShowPublishDateTimeProperty =
DependencyProperty.Register(nameof(IsShowPublishDateTime), typeof(bool), typeof(VideoItem), new PropertyMetadata(false));
/// <summary>
/// <see cref="IsShowReplayCount"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty IsShowReplayCountProperty =
DependencyProperty.Register(nameof(IsShowReplayCount), typeof(bool), typeof(VideoItem), new PropertyMetadata(false));
/// <summary>
/// <see cref="IsShowDanmakuCount"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty IsShowDanmakuCountProperty =
DependencyProperty.Register(nameof(IsShowDanmakuCount), typeof(bool), typeof(VideoItem), new PropertyMetadata(false));
/// <summary>
/// <see cref="IsShowPlayCount"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty IsShowPlayCountProperty =
DependencyProperty.Register(nameof(IsShowPlayCount), typeof(bool), typeof(VideoItem), new PropertyMetadata(false));
/// <summary>
/// <see cref="IsShowLikeCount"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty IsShowLikeCountProperty =
DependencyProperty.Register(nameof(IsShowLikeCount), typeof(bool), typeof(VideoItem), new PropertyMetadata(false));
/// <summary>
/// Initializes a new instance of the <see cref="VideoItem"/> class.
/// </summary>
......@@ -50,16 +81,57 @@ namespace Richasy.Bili.App.Controls
set { SetValue(OrientationProperty, value); }
}
/// <summary>
/// 是否显示播放数.
/// </summary>
public bool IsShowPlayCount
{
get { return (bool)GetValue(IsShowPlayCountProperty); }
set { SetValue(IsShowPlayCountProperty, value); }
}
/// <summary>
/// 是否显示弹幕数.
/// </summary>
public bool IsShowDanmakuCount
{
get { return (bool)GetValue(IsShowDanmakuCountProperty); }
set { SetValue(IsShowDanmakuCountProperty, value); }
}
/// <summary>
/// 是否显示回复数.
/// </summary>
public bool IsShowReplayCount
{
get { return (bool)GetValue(IsShowReplayCountProperty); }
set { SetValue(IsShowReplayCountProperty, value); }
}
/// <summary>
/// 是否显示发布时间.
/// </summary>
public bool IsShowPublishDateTime
{
get { return (bool)GetValue(IsShowPublishDateTimeProperty); }
set { SetValue(IsShowPublishDateTimeProperty, value); }
}
/// <summary>
/// 是否显示点赞数.
/// </summary>
public bool IsShowLikeCount
{
get { return (bool)GetValue(IsShowLikeCountProperty); }
set { SetValue(IsShowLikeCountProperty, value); }
}
private static void OnViewModelChanged(DependencyObject d, DependencyPropertyChangedEventArgs e)
{
var instance = d as VideoItem;
if (e.NewValue != null && e.NewValue is VideoViewModel vm)
{
var description = string.Empty;
var playStr = $"播放:{vm.PlayCount}";
var danmakuStr = $"弹幕:{vm.DanmakuCount}";
description = playStr + " · " + danmakuStr;
instance.DescriptionBlock.Text = description;
instance.CheckOrientation();
}
}
......@@ -97,5 +169,10 @@ namespace Richasy.Bili.App.Controls
private void OnContainerTapped(object sender, Windows.UI.Xaml.Input.TappedRoutedEventArgs e)
{
}
private void CoverImage_ImageFailed(in object sender, in ImageExFailedEventArgs e)
{
var msg = e.Exception.Message;
}
}
}
......@@ -43,13 +43,8 @@
x:Name="VideoRepeater"
Grid.Row="1"
ElementPrepared="OnElementPrepared"
ItemTemplate="{x:Bind ItemTemplate, Mode=OneWay}"
ItemsSource="{x:Bind ItemsSource, Mode=OneWay}"
Layout="{StaticResource GridLayout}">
<muxc:ItemsRepeater.ItemTemplate>
<DataTemplate x:DataType="uwp:VideoViewModel">
<local:VideoItem ViewModel="{x:Bind}" />
</DataTemplate>
</muxc:ItemsRepeater.ItemTemplate>
</muxc:ItemsRepeater>
Layout="{StaticResource GridLayout}" />
</Grid>
</UserControl>
......@@ -36,6 +36,12 @@ namespace Richasy.Bili.App.Controls
public static readonly DependencyProperty IsShowHeaderProperty =
DependencyProperty.Register(nameof(IsShowHeader), typeof(bool), typeof(VideoView), new PropertyMetadata(true));
/// <summary>
/// <see cref="ItemTemplate"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty ItemTemplateProperty =
DependencyProperty.Register(nameof(ItemTemplate), typeof(DataTemplate), typeof(VideoItem), new PropertyMetadata(null));
/// <summary>
/// Initializes a new instance of the <see cref="VideoView"/> class.
/// </summary>
......@@ -44,6 +50,15 @@ namespace Richasy.Bili.App.Controls
this.InitializeComponent();
}
/// <summary>
/// 条目模板.
/// </summary>
public DataTemplate ItemTemplate
{
get { return (DataTemplate)GetValue(ItemTemplateProperty); }
set { SetValue(ItemTemplateProperty, value); }
}
/// <summary>
/// 数据源.
/// </summary>
......
<UserControl
x:Class="Richasy.Bili.App.Controls.IconTextBlock"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:icons="using:Fluent.Icons"
xmlns:local="using:Richasy.Bili.App.Controls"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
d:DesignHeight="300"
d:DesignWidth="400"
mc:Ignorable="d">
<Grid ColumnSpacing="{x:Bind Spacing, Mode=OneWay}">
<Grid.ColumnDefinitions>
<ColumnDefinition Width="Auto" />
<ColumnDefinition Width="*" />
</Grid.ColumnDefinitions>
<Viewbox
Width="{x:Bind IconFontSize, Mode=OneWay}"
Height="{x:Bind IconFontSize, Mode=OneWay}"
VerticalAlignment="Center">
<icons:FluentIconElement Symbol="{x:Bind Symbol, Mode=OneWay}" />
</Viewbox>
<TextBlock
x:Name="ContentBlock"
Grid.Column="1"
VerticalAlignment="Center"
FontSize="{x:Bind FontSize, Mode=OneWay}"
Text="{x:Bind Text, Mode=OneWay}"
TextTrimming="CharacterEllipsis">
<ToolTipService.ToolTip>
<ToolTip Content="{x:Bind Text, Mode=OneWay}" IsEnabled="{x:Bind ContentBlock.IsTextTrimmed, Mode=OneWay}" />
</ToolTipService.ToolTip>
</TextBlock>
</Grid>
</UserControl>
// Copyright (c) Richasy. All rights reserved.
using Fluent.Icons;
using Windows.UI.Xaml;
using Windows.UI.Xaml.Controls;
namespace Richasy.Bili.App.Controls
{
/// <summary>
/// 带图标的文本.
/// </summary>
public sealed partial class IconTextBlock : UserControl
{
/// <summary>
/// <see cref="IconFontSize"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty IconFontSizeProperty =
DependencyProperty.Register(nameof(IconFontSize), typeof(double), typeof(IconTextBlock), new PropertyMetadata(14));
/// <summary>
/// <see cref="Spacing"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty SpacingProperty =
DependencyProperty.Register(nameof(Spacing), typeof(double), typeof(IconTextBlock), new PropertyMetadata(0));
/// <summary>
/// <see cref="Symbol"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty SymbolProperty =
DependencyProperty.Register(nameof(Symbol), typeof(FluentSymbol), typeof(IconTextBlock), new PropertyMetadata(default(FluentSymbol)));
/// <summary>
/// <see cref="Text"/>的依赖属性.
/// </summary>
public static readonly DependencyProperty TextProperty =
DependencyProperty.Register(nameof(Text), typeof(string), typeof(IconTextBlock), new PropertyMetadata(string.Empty));
/// <summary>
/// Initializes a new instance of the <see cref="IconTextBlock"/> class.
/// </summary>
public IconTextBlock()
{
this.InitializeComponent();
}
/// <summary>
/// 图标字体大小.
/// </summary>
public double IconFontSize
{
get { return (double)GetValue(IconFontSizeProperty); }
set { SetValue(IconFontSizeProperty, value); }
}
/// <summary>
/// 图标与文本的间距.
/// </summary>
public double Spacing
{
get { return (double)GetValue(SpacingProperty); }
set { SetValue(SpacingProperty, value); }
}
/// <summary>
/// 图标.
/// </summary>
public FluentSymbol Symbol
{
get { return (FluentSymbol)GetValue(SymbolProperty); }
set { SetValue(SymbolProperty, value); }
}
/// <summary>
/// 文本.
/// </summary>
public string Text
{
get { return (string)GetValue(TextProperty); }
set { SetValue(TextProperty, value); }
}
}
}
......@@ -115,7 +115,7 @@ namespace Richasy.Bili.App.Controls
_realizedElements.AddOrInsert(realizedIndex, element);
// Set bounds to an invalid rect since we do not know it yet.
_realizedElementLayoutBounds.AddOrInsert(realizedIndex, new Rect(-1, -1, -1, -1));
_realizedElementLayoutBounds.AddOrInsert(realizedIndex, new Rect(0, 0, 0, 0));
}
public void ClearRealizedRange(int realizedIndex, int count)
......
......@@ -4,11 +4,11 @@
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Richasy.Bili.App.Controls"
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
xmlns:loc="using:Richasy.Bili.Locator.Uwp"
xmlns:local="using:Richasy.Bili.App.Pages.Overlay"
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:muxc="using:Microsoft.UI.Xaml.Controls"
xmlns:uwp="using:Richasy.Bili.ViewModels.Uwp"
xmlns:loc="using:Richasy.Bili.Locator.Uwp"
mc:Ignorable="d">
<Grid>
......@@ -97,7 +97,17 @@
Grid.Row="1"
Margin="0,0,0,12"
HeaderText="{loc:LocaleLocator Name=ComprehensiveDynamics}"
ItemsSource="{x:Bind ViewModel.CurrentSelectedSubPartition.VideoCollection, Mode=OneWay}" />
ItemsSource="{x:Bind ViewModel.CurrentSelectedSubPartition.VideoCollection, Mode=OneWay}">
<controls:VideoView.ItemTemplate>
<DataTemplate x:DataType="uwp:VideoViewModel">
<controls:VideoItem
IsShowDanmakuCount="True"
IsShowLikeCount="True"
IsShowPlayCount="True"
ViewModel="{x:Bind}" />
</DataTemplate>
</controls:VideoView.ItemTemplate>
</controls:VideoView>
<muxc:ProgressRing
x:Name="LoadingRing"
......
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
xmlns:controls="using:Richasy.Bili.App.Controls"
xmlns:local="using:Richasy.Bili.App">
<Style TargetType="controls:BannerItem">
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="controls:BannerItem">
<Grid x:Name="RootGrid" CornerRadius="{StaticResource ControlCornerRadius}">
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonGroup">
<VisualState x:Name="NormalState" />
<VisualState x:Name="PressedState">
<VisualState.Storyboard>
<Storyboard>
<PointerDownThemeAnimation Storyboard.TargetName="BannerImage" />
</Storyboard>
</VisualState.Storyboard>
</VisualState>
<VisualState x:Name="ReleaseState">
<VisualState.Storyboard>
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="BannerImage" />
</Storyboard>
</VisualState.Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Image
x:Name="BannerImage"
AutomationProperties.Name="{TemplateBinding Title}"
MaxHeight="114"
Source="{TemplateBinding Source}"
Stretch="Uniform"
ToolTipService.ToolTip="{TemplateBinding Title}" />
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
......@@ -35,15 +35,15 @@ namespace Richasy.Bili.Toolkit.Uwp
var resourceToolkit = ServiceLocator.Instance.GetService<IResourceToolkit>();
if (timeSpan.TotalHours > 1)
{
return Math.Round(timeSpan.TotalHours, 2) + resourceToolkit.GetLocaleString(Models.Enums.LanguageNames.Hours);
return Math.Round(timeSpan.TotalHours, 2) + " " + resourceToolkit.GetLocaleString(Models.Enums.LanguageNames.Hours);
}
else if (timeSpan.TotalMinutes > 1)
{
return Math.Round(timeSpan.TotalMinutes) + resourceToolkit.GetLocaleString(Models.Enums.LanguageNames.Minutes);
return Math.Round(timeSpan.TotalMinutes) + " " + resourceToolkit.GetLocaleString(Models.Enums.LanguageNames.Minutes);
}
else
{
return Math.Round(timeSpan.TotalSeconds) + resourceToolkit.GetLocaleString(Models.Enums.LanguageNames.Seconds);
return Math.Round(timeSpan.TotalSeconds) + " " + resourceToolkit.GetLocaleString(Models.Enums.LanguageNames.Seconds);
}
}
}
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册