你需要创建一个自定义的列表视图渲染器并对其应用自定义样式。
创建一个派生的ListView:
namespace MyApp.Controls
{
public class MyListView : Xamarin.Forms.ListView
{
}
}
在您的视图中将ListView更改为您派生的控件:
<?xml version="1.0" encoding="utf-8" ?>
<ContentView
xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
xmlns:controls="clr-namespace:MyApp.Controls"
x:Class="MyApp.MyView">
<controls:MyListView
ItemsSource="{Binding ListSource}"
SelectionMode="None"
SeparatorVisibility="None">
// ...
// template
// ..
</controls:CustomListView>
</ContentView>
在您的UWP项目中创建一个列表视图渲染器:
[assembly: ExportRenderer(typeof(MyListView), typeof(MyListViewRenderer))]
namespace MyApp
{
class MyListViewRenderer : ListViewRenderer
{
protected override void OnElementChanged(ElementChangedEventArgs<ListView> e)
{
base.OnElementChanged(e);
if (Control is Windows.UI.Xaml.Controls.ListView listView)
{
listView.ItemContainerStyle = (Windows.UI.Xaml.Style)MyApp.App.Current.Resources["CustomListViewItem"];
}
}
}
}
现在您需要定义上述CustomListViewItem样式。
Windows控件的默认样式定义在generic.xaml文件中,可以在以下本地路径中找到:
C:\Program Files (x86)\Windows Kits\10\DesignTime\CommonConfiguration\Neutral\UAP\10.0.18362.0\Generic
在其中,您将找到默认的列表视图项样式,称为ListViewItemExpanded,您需要修改其样式并将其加载到资源字典中。
以下是一个简化版本(保存为CustomListViewItem.xaml):
<ResourceDictionary
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
<Style x:Key="CustomListViewItem" TargetType="ListViewItem">
<Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}" />
<Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}" />
<Setter Property="BorderBrush" Value="{x:Null}" />
<Setter Property="BorderThickness" Value="0" />
<Setter Property="Background" Value="Transparent" />
<Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}" />
<Setter Property="TabNavigation" Value="Local" />
<Setter Property="IsHoldingEnabled" Value="True" />
<Setter Property="Padding" Value="0,0,0,0" />
<Setter Property="HorizontalContentAlignment" Value="Left" />
<Setter Property="VerticalContentAlignment" Value="Center" />
<Setter Property="MinWidth" Value="{ThemeResource ListViewItemMinWidth}" />
<Setter Property="MinHeight" Value="{ThemeResource ListViewItemMinHeight}" />
<Setter Property="AllowDrop" Value="False" />
<Setter Property="UseSystemFocusVisuals" Value="{StaticResource UseSystemFocusVisuals}" />
<Setter Property="FocusVisualMargin" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ListViewItem">
<Grid x:Name="ContentBorder"
Control.IsTemplateFocusTarget="True"
FocusVisualMargin="{TemplateBinding FocusVisualMargin}"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}"
CornerRadius="{TemplateBinding CornerRadius}"
RenderTransformOrigin="0.5,0.5">
<Grid.RenderTransform>
<ScaleTransform x:Name="ContentBorderScale" />
</Grid.RenderTransform>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal">
<Storyboard>
<PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BorderBackground"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="1" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectSquare" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectCheck" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="BorderBackground"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="1" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListMediumBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectSquare" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectCheck" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<!--<PointerDownThemeAnimation TargetName="ContentPresenter" />-->
</Storyboard>
</VisualState>
<VisualState x:Name="Selected">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MultiSelectCheck"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0"
To="1" />
<DoubleAnimation Storyboard.TargetName="BorderBackground"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="1" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListAccentLowBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectSquare" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectCheck" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerOverSelected">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MultiSelectCheck"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0"
To="1" />
<DoubleAnimation Storyboard.TargetName="BorderBackground"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="1" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListAccentMediumBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectSquare" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectCheck" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<PointerUpThemeAnimation Storyboard.TargetName="ContentPresenter" />
</Storyboard>
</VisualState>
<VisualState x:Name="PressedSelected">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="MultiSelectCheck"
Storyboard.TargetProperty="Opacity"
Duration="0:0:0"
To="1" />
<DoubleAnimation Storyboard.TargetName="BorderBackground"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="1" />
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="BorderBackground" Storyboard.TargetProperty="Fill">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightListAccentHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenter" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectSquare" Storyboard.TargetProperty="BorderBrush">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectCheck" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightAltBaseHighBrush}" />
</ObjectAnimationUsingKeyFrames>
<PointerDownThemeAnimation TargetName="ContentPresenter" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="DisabledStates">
<VisualState x:Name="Enabled" />
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="ContentBorder"
Storyboard.TargetProperty="Opacity"
Duration="0"
To="{ThemeResource ListViewItemDisabledThemeOpacity}" />
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="MultiSelectStates">
<VisualState x:Name="MultiSelectDisabled">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectCheckBoxTransform" Storyboard.TargetProperty="X">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0" />
<SplineDoubleKeyFrame KeyTime="0:0:0.333" Value="-32" KeySpline="0.1,0.9,0.2,1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectClipTransform" Storyboard.TargetProperty="X">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="0" />
<SplineDoubleKeyFrame KeyTime="0:0:0.333" Value="32" KeySpline="0.1,0.9,0.2,1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenterTranslateTransform" Storyboard.TargetProperty="X">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="32" />
<SplineDoubleKeyFrame KeyTime="0:0:0.333" Value="0" KeySpline="0.1,0.9,0.2,1" />
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectSquare" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
<DiscreteObjectKeyFrame KeyTime="0:0:0.333" Value="Collapsed" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="MultiSelectEnabled">
<Storyboard>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectCheckBoxTransform" Storyboard.TargetProperty="X">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="-32" />
<SplineDoubleKeyFrame KeyTime="0:0:0.333" Value="0" KeySpline="0.1,0.9,0.2,1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectClipTransform" Storyboard.TargetProperty="X">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="32" />
<SplineDoubleKeyFrame KeyTime="0:0:0.333" Value="0" KeySpline="0.1,0.9,0.2,1" />
</DoubleAnimationUsingKeyFrames>
<DoubleAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenterTranslateTransform" Storyboard.TargetProperty="X">
<EasingDoubleKeyFrame KeyTime="0:0:0" Value="-32" />
<SplineDoubleKeyFrame KeyTime="0:0:0.333" Value="0" KeySpline="0.1,0.9,0.2,1" />
</DoubleAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectSquare" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="MultiSelectCheck" Storyboard.TargetProperty="Visibility">
<DiscreteObjectKeyFrame KeyTime="0" Value="Visible" />
</ObjectAnimationUsingKeyFrames>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="ContentPresenterGrid" Storyboard.TargetProperty="Margin">
<DiscreteObjectKeyFrame KeyTime="0" Value="32,0,0,0" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
<Rectangle x:Name="BorderBackground"
IsHitTestVisible="False"
Fill="{ThemeResource SystemControlHighlightListAccentLowBrush}"
Opacity="0"
Control.IsTemplateFocusTarget="True" />
<Grid x:Name="ContentPresenterGrid" Background="Transparent" Margin="0,0,0,0">
<Grid.RenderTransform>
<TranslateTransform x:Name="ContentPresenterTranslateTransform" />
</Grid.RenderTransform>
<ContentPresenter x:Name="ContentPresenter"
ContentTransitions="{TemplateBinding ContentTransitions}"
ContentTemplate="{TemplateBinding ContentTemplate}"
Content="{TemplateBinding Content}"
HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Margin="{TemplateBinding Padding}" />
</Grid>
<!-- The 'Xg' text simulates the amount of space one line of text will occupy.
In the DataPlaceholder state, the Content is not loaded yet so we
approximate the size of the item using placeholder text. -->
<TextBlock x:Name="PlaceholderTextBlock"
Opacity="0"
Text="Xg"
Foreground="{x:Null}"
Margin="{TemplateBinding Padding}"
IsHitTestVisible="False"
AutomationProperties.AccessibilityView="Raw" />
<Rectangle x:Name="PlaceholderRect" Visibility="Collapsed" Fill="{ThemeResource ListViewItemPlaceholderBackground}" />
<Border x:Name="MultiSelectSquare"
BorderBrush="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
BorderThickness="2"
Width="20"
Height="20"
Margin="12,0,0,0"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Visibility="Collapsed">
<Border.Clip>
<RectangleGeometry Rect="0,0,20,20">
<RectangleGeometry.Transform>
<TranslateTransform x:Name="MultiSelectClipTransform" />
</RectangleGeometry.Transform>
</RectangleGeometry>
</Border.Clip>
<Border.RenderTransform>
<TranslateTransform x:Name="MultiSelectCheckBoxTransform" />
</Border.RenderTransform>
<FontIcon x:Name="MultiSelectCheck"
FontFamily="{ThemeResource SymbolThemeFontFamily}"
Glyph=""
FontSize="16"
Foreground="{ThemeResource SystemControlForegroundBaseMediumHighBrush}"
Visibility="Collapsed"
Opacity="0" />
</Border>
<Border x:Name="MultiArrangeOverlayTextBorder"
Opacity="0"
IsHitTestVisible="False"
Margin="12,0,0,0"
MinWidth="20"
Height="20"
VerticalAlignment="Center"
HorizontalAlignment="Left"
Background="{ThemeResource SystemControlBackgroundAccentBrush}"
BorderThickness="2"
BorderBrush="{ThemeResource SystemControlBackgroundChromeWhiteBrush}">
<TextBlock x:Name="MultiArrangeOverlayText"
Text="{Binding RelativeSource={RelativeSource TemplatedParent}, Path=TemplateSettings.DragItemsCount}"
Style="{ThemeResource CaptionTextBlockStyle}"
IsHitTestVisible="False"
Opacity="0"
VerticalAlignment="Center"
HorizontalAlignment="Center"
AutomationProperties.AccessibilityView="Raw" />
</Border>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
</ResourceDictionary>
请注意,在按下的可视状态中,
<PointerDownThemeAnimation TargetName="ContentPresenter" />
被注释掉了。
现在将该资源加载到您的应用程序中:
<Application
x:Class="MyApp.App"
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">
<Application.Resources>
<ResourceDictionary>
<ResourceDictionary.MergedDictionaries>
<ResourceDictionary Source="/Styles/CustomListViewItem.xaml"/>
</ResourceDictionary.MergedDictionaries>
</ResourceDictionary>
</Application.Resources>
</Application>
你可能需要进一步调整样式,但基本上就是这样。
顺便说一下,这种方法也可以用来调整 UWP 中任何本地控件的外观。