我目前正在处理的 UWP 项目有问题:
我有一个这样的视图模型:
public class HomePageViewModel : INotifyPropertyChanged
{
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<WidgetViewModel> Widgets { get; } = new ObservableCollection<WidgetViewModel>();
public HomePageViewModel()
{
}
public void OnNotifyPropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
WidgetViewModel 的定义如下:
public class WidgetViewModel : INotifyPropertyChanged
{
private string group;
public string Group
{
get=>group;
set
{
group=value;
OnNotifyPropertyChanged();
}
}
public event PropertyChangedEventHandler PropertyChanged;
public ObservableCollection<ItemViewModel> Items { get; } = new ObservableCollection<ItemViewModel>();
public WidgetPageViewModel()
{
}
public void OnNotifyPropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
我的 ItemViewModel 是这样定义的:
public class ItemViewModel : INotifyPropertyChanged
{
private string name;
public event PropertyChangedEventHandler PropertyChanged;
public string Name
{
get=>name;
set
{
name = value;
OnNotifyPropertyChanged();
}
}
public ItemViewModel()
{
}
public void OnNotifyPropertyChanged([CallerMemberName]string propertyName = "")
{
PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(propertyName));
}
}
我制作了这个 xaml :
<Page x:Class="Project.TestPage"
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:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
xmlns:local="Project"
Background="{ThemeResource ApplicationPageBackgroundThemeBrush}"
mc:Ignorable="d">
<Grid>
<Grid.Resources>
<CollectionViewSource x:Name="TestSource"
IsSourceGrouped="True"
Source="{Binding Widgets}" />
<local:ItemTemplateSelector x:Key="ItemTemplateSelector">
<local:ItemTemplateSelector.WidgetTemplate>
<DataTemplate>
<local:TestItemsControl ItemTemplateSelector="{StaticResource ItemTemplateSelector}"
ItemsSource="{Binding Items}">
<local:TestItemsControl.ItemContainerStyle>
<Style TargetType="local:TestItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
</local:TestItemsControl.ItemContainerStyle>
</local:TestItemsControl>
</DataTemplate>
</local:ItemTemplateSelector.WidgetTemplate>
<local:ItemTemplateSelector.ItemTemplate>
<DataTemplate>
<TextBlock Text="{Binding Name}" />
</DataTemplate>
</local:ItemTemplateSelector.ItemTemplate>
</local:ItemTemplateSelector>
<x:String x:Key="ChevronGlyph"></x:String>
<Style x:Key="TextButtonStyle" TargetType="ButtonBase">
<Setter Property="MinWidth" Value="0" />
<Setter Property="MinHeight" Value="0" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="ButtonBase">
<Grid Background="Transparent">
<ContentPresenter x:Name="Text" Content="{TemplateBinding Content}" />
<Rectangle x:Name="FocusVisualWhite"
IsHitTestVisible="False"
Opacity="0"
Stroke="{StaticResource FocusVisualWhiteStrokeThemeBrush}"
StrokeDashArray="1,1"
StrokeDashOffset="1.5"
StrokeEndLineCap="Square" />
<Rectangle x:Name="FocusVisualBlack"
IsHitTestVisible="False"
Opacity="0"
Stroke="{StaticResource FocusVisualBlackStrokeThemeBrush}"
StrokeDashArray="1,1"
StrokeDashOffset="0.5"
StrokeEndLineCap="Square" />
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPointerOverForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Pressed">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPressedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Disabled">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationPressedForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
</VisualStateGroup>
<VisualStateGroup x:Name="FocusStates">
<VisualState x:Name="Focused">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="FocusVisualWhite"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
<DoubleAnimation Storyboard.TargetName="FocusVisualBlack"
Storyboard.TargetProperty="Opacity"
To="1"
Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="Unfocused" />
</VisualStateGroup>
<VisualStateGroup x:Name="CheckStates">
<VisualState x:Name="Checked" />
<VisualState x:Name="Unchecked">
<Storyboard>
<ObjectAnimationUsingKeyFrames Storyboard.TargetName="Text" Storyboard.TargetProperty="Foreground">
<DiscreteObjectKeyFrame KeyTime="0" Value="{StaticResource ApplicationSecondaryForegroundThemeBrush}" />
</ObjectAnimationUsingKeyFrames>
</Storyboard>
</VisualState>
<VisualState x:Name="Indeterminate" />
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style x:Key="TextPrimaryButtonStyle"
BasedOn="{StaticResource TextButtonStyle}"
TargetType="ButtonBase">
<Setter Property="Foreground" Value="{StaticResource ApplicationHeaderForegroundThemeBrush}" />
</Style>
<Style x:Key="GroupHeaderTextStyle" TargetType="TextBlock">
<Setter Property="FontFamily" Value="{StaticResource ContentControlThemeFontFamily}" />
<Setter Property="TextTrimming" Value="WordEllipsis" />
<Setter Property="TextWrapping" Value="NoWrap" />
<Setter Property="Typography.StylisticSet20" Value="True" />
<Setter Property="Typography.DiscretionaryLigatures" Value="True" />
<Setter Property="Typography.CaseSensitiveForms" Value="True" />
<Setter Property="FontSize" Value="26.667" />
<Setter Property="LineStackingStrategy" Value="BlockLineHeight" />
<Setter Property="FontWeight" Value="Light" />
<Setter Property="LineHeight" Value="30" />
<Setter Property="RenderTransform">
<Setter.Value>
<TranslateTransform X="-1" Y="6" />
</Setter.Value>
</Setter>
</Style>
</Grid.Resources>
<Grid.RowDefinitions>
<RowDefinition Height="Auto" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<GridView Grid.Row="1"
Padding="116,137,40,46"
IsItemClickEnabled="False"
ItemTemplateSelector="{StaticResource ItemTemplateSelector}"
ItemsSource="{Binding Source={StaticResource TestSource}}"
ScrollViewer.HorizontalScrollBarVisibility="Auto"
ScrollViewer.HorizontalScrollMode="Enabled"
ScrollViewer.VerticalScrollBarVisibility="Disabled"
ScrollViewer.VerticalScrollMode="Disabled">
<GridView.ItemContainerStyle>
<Style TargetType="GridViewItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
</Style>
</GridView.ItemContainerStyle>
<GridView.GroupStyle>
<GroupStyle>
<GroupStyle.HeaderTemplate>
<DataTemplate>
<Button AutomationProperties.Name="Group Title" Style="{StaticResource TextPrimaryButtonStyle}">
<StackPanel Orientation="Horizontal">
<TextBlock Margin="3,-7,10,10"
Style="{StaticResource GroupHeaderTextStyle}"
Text="{Binding Key}" />
<TextBlock Margin="0,-7,0,10"
FontFamily="Segoe UI Symbol"
Style="{StaticResource GroupHeaderTextStyle}"
Text="{StaticResource ChevronGlyph}" />
</StackPanel>
</Button>
</DataTemplate>
</GroupStyle.HeaderTemplate>
<GroupStyle.Panel>
<ItemsPanelTemplate>
<VariableSizedWrapGrid Margin="0,0,80,0"
ItemHeight="200"
ItemWidth="200"
Orientation="Vertical" />
</ItemsPanelTemplate>
</GroupStyle.Panel>
</GroupStyle>
</GridView.GroupStyle>
<GridView.ItemsPanel>
<ItemsPanelTemplate>
<StackPanel Orientation="Horizontal" />
</ItemsPanelTemplate>
</GridView.ItemsPanel>
</GridView>
</Grid>
</Page>
ItemTemplateSelector 的定义如下:
public sealed class ItemTemplateSelector
: DataTemplateSelector
{
public DataTemplate WidgetTemplate{get;set;}
public DataTemplate ItemTemplate{get;set;}
/// <summary>
///
/// </summary>
/// <param name="item"></param>
/// <returns></returns>
protected override DataTemplate SelectTemplateCore(object item)
{
if(item is ItemViewModel)
return ItemTemplate;
if(item is WidgetViewModel)
return WidgetTemplate;
return null;
}
protected override DataTemplate SelectTemplateCore(object item, DependencyObject container)
{
if(item is ItemViewModel)
return ItemTemplate;
if(item is WidgetViewModel)
return WidgetTemplate;
return null;
}
}
}
TestItemsControl 是:
public class TestItemsControl : ItemsControl
{
public TestItemsControl()
{
DefaultStyleKey = typeof(TestItemsControl);
}
protected override bool IsItemItsOwnContainerOverride(object item)
{
return item is TestItem;
}
protected override DependencyObject GetContainerForItemOverride()
{
return new TestItem();
}
}
TestItem 基本上是:
public class TestItem : ContentControl
{
public TestItem()
{
DefaultStyleKey = typeof(TestItem);
}
}
他们的风格:
<Style TargetType="local:TestItem">
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TestItem">
<Border Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid>
<ContentPresenter HorizontalAlignment="{TemplateBinding HorizontalContentAlignment}"
VerticalAlignment="{TemplateBinding VerticalContentAlignment}"
Content="{TemplateBinding Content}"
ContentTemplate="{TemplateBinding ContentTemplate}"
ContentTemplateSelector="{TemplateBinding ContentTemplateSelector}"
FontFamily="{TemplateBinding FontFamily}"
FontSize="{TemplateBinding FontSize}"
FontStyle="{TemplateBinding FontStyle}"
FontWeight="{TemplateBinding FontWeight}"
Foreground="{TemplateBinding Foreground}" />
</Grid>
</Border>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
<Style TargetType="local:TestItemsControl">
<Setter Property="Padding" Value="0" />
<Setter Property="Margin" Value="0" />
<Setter Property="BorderBrush" Value="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
<Setter Property="Background" Value="{ThemeResource ApplicationPageBackgroundThemeBrush}" />
<Setter Property="Foreground" Value="Black" />
<Setter Property="HorizontalAlignment" Value="Stretch" />
<Setter Property="VerticalAlignment" Value="Stretch" />
<Setter Property="VerticalContentAlignment" Value="Stretch" />
<Setter Property="HorizontalContentAlignment" Value="Stretch" />
<Setter Property="ItemsPanel">
<Setter.Value>
<ItemsPanelTemplate>
<VariableSizedWrapGrid />
</ItemsPanelTemplate>
</Setter.Value>
</Setter>
<Setter Property="Template">
<Setter.Value>
<ControlTemplate TargetType="local:TestItemsControl">
<Grid x:Name="PART_Root">
<Rectangle x:Name="PointerOverRect"
Margin="-2"
Fill="#DE000000"
Opacity="0" />
<Border x:Name="PART_Border"
Background="{TemplateBinding Background}"
BorderBrush="{TemplateBinding BorderBrush}"
BorderThickness="{TemplateBinding BorderThickness}">
<Grid Margin="{TemplateBinding Padding}">
<ItemsPresenter />
</Grid>
</Border>
<VisualStateManager.VisualStateGroups>
<VisualStateGroup x:Name="CommonStates">
<VisualState x:Name="Normal" />
<VisualState x:Name="PointerOver">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PointerOverRect"
Storyboard.TargetProperty="Opacity"
To="0.28"
Duration="0" />
</Storyboard>
</VisualState>
<VisualState x:Name="PointerPressed" />
<VisualState x:Name="Disabled">
<Storyboard>
<DoubleAnimation Storyboard.TargetName="PART_Border"
Storyboard.TargetProperty="Opacity"
To="0.3"
Duration="0" />
</Storyboard>
</VisualState>
</VisualStateGroup>
</VisualStateManager.VisualStateGroups>
</Grid>
</ControlTemplate>
</Setter.Value>
</Setter>
</Style>
最后是我如何创建项目:
public class TestPage : Page
{
public TestPage()
{
InitializeComponent();
var vm = new HomePageViewModel();
DataContext = vm;
var widget = new WidgetViewModel();
widget.Add(new ItemViewModel
{
Name = "Users"
});
widget.Add(new ItemViewModel
{
Name = "16"
});
vm.Widgets.Add(widget);
}
}
我有两个问题:(
第一个问题是:ItemTemplate 已设置,但它不显示项目的名称,但此文本:“Project.ItemViewModel”,我不明白为什么
第二个问题是子容器没有填满它的父容器。
为了解释我想要实现的目标,基本思想是让一个组件在延迟后交换其内容。
所以在这里我有一个带有项目的 GridView,每个项目都可以有很多内容。
这就是我使用TestItemsControl 的原因。用它管理交换内容更容易......
有任何想法吗?
编辑:我做了一些步骤。我还有一个问题。它是:DataTemplate 已设置到容器中,但未应用。当我在 DataTemplateSelector 上断点时,我看到我的 TestItemContainer 并在其中设置了 DataTemplateSelector,但是该项目始终显示一个带有文本“XXXX.XXXX.ViewModel”的文本块并且使用数据模板我需要显示属性“名称”视图模型
谢谢你的帮助