如何正确地使用新属性扩展XAML控件?

问题描述 投票:0回答:3

我有一个新的哲学问题,旨在强调旧的 WPF 模式和新的 UWP 模式之间的差异。

我想在 UWP 环境而不是 WPF 环境中使用新属性扩展标准控件(例如按钮)。

在 WPF 中,我注意到可以使用两个文件创建自定义控件:Themes/Generics.xaml 和 MyCustomControl.cs。

在 UWP 中,它仅创建 .cs 文件...这是否意味着如果我想修改 Button 的 XAML 内容(假设我想创建一个 IconButton:内容为 SymbolIcon 的 Button 且一个文本块),这不可能吗?

我知道我可以使用“用户控件”,但它是一个通用控件,我会失去我想要自定义的控件的所有属性(例如,在我的情况下,Click 事件等)...我什至可以扩展用户控件以包含所需控件的所有属性...但这会花费太长时间。

说到这一点:在 UWP 环境中通过代码和 Xaml 自定义和扩展标准 XAML 控件的最佳和正确方法是什么?

举个例子,考虑一个经典任务:创建一个 IconButton,正如我上面所说...一个 Button,其内容是一个带有 SymbolIcon 和 Textblock 作为子项的网格。

谢谢你。

c# xaml uwp uwp-xaml
3个回答
6
投票

你想要这样的东西吗---

XAML

如果您有单个按钮---

<Button>
    <Grid>
        <Grid.RowDefinitions>
            <RowDefinition Height="Auto"/>
            <RowDefinition Height="*"/>
        </Grid.RowDefinitions>
        <TextBlock Grid.Row="0" FontFamily="Segoe MDL2 Assets" Text="&#xECAD;" HorizontalAlignment="Center"/> <!-- alternately use your icon image -->
        <TextBlock Grid.Row="1" Text="Click me!"/>
    </Grid>            
</Button>

输出

Output

如果您有多个按钮,请使用该模板--

步骤-

1)创建一个类“ButtonWithIcon.cs”或xyz.cs。

public class AdvancedButton : Button
{
    public static readonly DependencyProperty IconContentProperty =
      DependencyProperty.Register("Icon", typeof(string), typeof(AdvancedButton), new PropertyMetadata(default(FontIcon)));

    public string Icon
    {
        get { return (string)GetValue(IconContentProperty); }
        set { SetValue(IconContentProperty, value); }
    }
}

2)然后在 Page.xaml(仅用于一页)或 app.xaml(用于整个应用程序)中添加该模板

<Style x:Key="AdvancedButtonTemplate" TargetType="local:AdvancedButton">
    <Setter Property="Background" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}"/>
    <Setter Property="Foreground" Value="{ThemeResource SystemControlForegroundBaseHighBrush}"/>
    <Setter Property="BorderBrush" Value="{ThemeResource SystemControlForegroundTransparentBrush}"/>
    <Setter Property="BorderThickness" Value="{ThemeResource ButtonBorderThemeThickness}"/>
    <Setter Property="Padding" Value="8,4,8,4"/>
    <Setter Property="HorizontalAlignment" Value="Left"/>
    <Setter Property="VerticalAlignment" Value="Center"/>
    <Setter Property="FontFamily" Value="{ThemeResource ContentControlThemeFontFamily}"/>
    <Setter Property="FontWeight" Value="Normal"/>
    <Setter Property="FontSize" Value="{ThemeResource ControlContentThemeFontSize}"/>
    <Setter Property="UseSystemFocusVisuals" Value="True"/>
    <Setter Property="Template">
        <Setter.Value>
            <ControlTemplate TargetType="local:AdvancedButton">
                <Grid x:Name="RootGrid" Background="{TemplateBinding Background}">
                    <Grid.RowDefinitions>
                        <RowDefinition Height="Auto"/>
                        <RowDefinition Height="*"/>
                    </Grid.RowDefinitions>
                    <VisualStateManager.VisualStateGroups>
                        <VisualStateGroup x:Name="CommonStates">
                            <VisualState x:Name="Normal">
                                <Storyboard>
                                    <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="PointerOver">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ContentPresenter">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseMediumLowBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
                                    <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <PointerUpThemeAnimation Storyboard.TargetName="RootGrid"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Pressed">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="RootGrid">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseMediumLowBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ContentPresenter">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightTransparentBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlHighlightBaseHighBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <PointerDownThemeAnimation Storyboard.TargetName="RootGrid"/>
                                </Storyboard>
                            </VisualState>
                            <VisualState x:Name="Disabled">
                                <Storyboard>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Background" Storyboard.TargetName="RootGrid">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlBackgroundBaseLowBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="Foreground" Storyboard.TargetName="ContentPresenter">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledBaseLowBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                    <ObjectAnimationUsingKeyFrames Storyboard.TargetProperty="BorderBrush" Storyboard.TargetName="ContentPresenter">
                                        <DiscreteObjectKeyFrame KeyTime="0" Value="{ThemeResource SystemControlDisabledTransparentBrush}"/>
                                    </ObjectAnimationUsingKeyFrames>
                                </Storyboard>
                            </VisualState>
                        </VisualStateGroup>
                    </VisualStateManager.VisualStateGroups>                            
                        <TextBlock x:Name="FontIcon" Grid.Row="0" Text="{Binding Icon, RelativeSource={RelativeSource TemplatedParent}}" Width="40" Foreground="{TemplateBinding Foreground}" FontSize="32" VerticalAlignment="Center" RenderTransformOrigin="0.5,0.5" FontFamily="Segoe MDL2 Assets"/>
                    <TextBlock x:Name="Text" Grid.Row="1" Text="{TemplateBinding Content}" VerticalAlignment="Center" Foreground="{TemplateBinding Foreground}" TextAlignment="Center" RenderTransformOrigin="0.5,0.5"/>
                    <ContentPresenter x:Name="ContentPresenter" Grid.Row="0" Grid.RowSpan="2" ContentTemplate="{TemplateBinding ContentTemplate}" ContentTransitions="{TemplateBinding ContentTransitions}" Content="" AutomationProperties.AccessibilityView="Raw" BorderBrush="{TemplateBinding BorderBrush}" BorderThickness="{TemplateBinding BorderThickness}" HorizontalContentAlignment="{TemplateBinding HorizontalContentAlignment}" Padding="{TemplateBinding Padding}" VerticalContentAlignment="{TemplateBinding VerticalContentAlignment}"/>
                </Grid>
            </ControlTemplate>
        </Setter.Value>
    </Setter>
</Style>

3)然后在页面中您想要的位置使用该自定义按钮

<local:AdvancedButton Height="55" Width="250" Style="{StaticResource AdvancedButtonTemplate}" Content="New" Icon="&#xECAD;" BorderThickness="1" BorderBrush="Black" />

4)构建解决方案,否则它将显示蓝色错误下划线。

输出

注意:这里我根据我的正常理解自定义模板,您需要根据您的需要在模板中自定义一些字体大小和样式,如果您需要在模板中的文本块中添加边距 - 查看最后 3 个元素“textblocks”,“内容主持人”。

Output


4
投票

定制和扩展标准的最佳和正确方法是什么 在 UWP 环境中通过代码和 Xaml 进行 XAML 控制?

简单回答:可以使用模板化的Control模板。

有一个关于此的视频,您可以从这个视频的30分钟开始。

一般来说,我们自定义控件有两种方式:

  1. 用户控制
  2. 模板化控件

对于UserControl,它用于轻量级定制,您只需要在自己的项目中使用它即可。 对于模板化控件来说,这是我们自定义控件的基本方式。 对于您的场景,实际上这里不会有太多差异,您可以继承您想要的控件,然后使用您的代码从代码级别和 Xaml 级别对其进行自定义。


0
投票

今天我了解到,我可以通过首先创建 UserControl 然后将“UserControl”部分替换为我想要的控件来本地扩展控件(无需包装在 UserControl 中)。我做了一个 RibbonTab。

首先在 MyRibbonTab.xaml.cs 中:

public partial class MyRibbonTab: RibbonTab

然后我进入 MyRibbonTab.xaml 并删除所有内容并将其替换为:

<RibbonTab x:Class="MyNamespace.MyRibbonTab"
    xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
    xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
    Header="MyTabHeader">
  <RibbonGroup>
    ...
  </RibbonGroup>
</RibbonTab>

我没想到这会起作用,但它确实起作用了。我可以简单地执行此操作(在指定 xmlns:rib 之后),而不是为功能区及其所有选项卡中的所有按钮和控件提供数千行 xml 的疯狂功能区:

<Ribbon x:Name="MyCustom_rbn" VerticalAlignment="Top">
  <rib:MyRibbonTab x:Name="MyRibbon_tab"></rib:MyRibbonTab>
</Ribbon>

如此干净简单。当然,这是 WPF - 我假设对于 UWP,您必须将 xmlns 和 xmlns:x 更改为 UWP 的。有趣的是,没有关于此类内容的教程或信息 - 我只是猜测我的解决方案。

© www.soinside.com 2019 - 2024. All rights reserved.