Marvin's Blog【程式人生】

Ability will never catch up with the demand for it

24 Oct 2020

XAML经验合集【一】

3 Techniques you can use to make your data templates dynamic

  • Value Converters
  • Visual State Manager
  • Data Template Selectors

Overriding Resources from Generic.xaml in UWP Applications

没整明白Generic.xaml中的资源比App.xaml中的资源优先级高还是低?回复中有这么一段话:

I don't think WPF application will do what you want. Actually, it's related to the resource lookup behavior. The generic.xaml in theme folder will be always the first place to lookup for this scenario. 

How do I reference a StaticResource in code-behind?

可以通过FrameworkElement的Resources下属来访问XAML中定义的资源:

foo2.Style = this.Resources["NavigationBackButtonNormalStyle"] as Style;

想访问再App级别定义的XAML资源,可以如下操作:

play_btn.Style = App.Current.Resources["btnplay"] as Style;

参考Why am I not able to use FindResource() in Windows phone programming?

WPF的话,有TryFindResource方法可以遍历前序XAML元素的Resources下属。

对于UWP来说,可能需要自己定义TryFindResource(参考How to set ItemsSource property programmatically?):

public static class FrameworkElementExtensions
{
    public static object TryFindResource(this FrameworkElement element, object resourceKey)
    {
        var currentElement = element;

        while (currentElement != null)
        {
            var resource = currentElement.Resources[resourceKey];
            if (resource != null)
            {
                return resource;
            }

            currentElement = currentElement.Parent as FrameworkElement;
        }

        return Application.Current.Resources[resourceKey];
    }
}

/**********************************************************************/
// Or, the recursive version of TryFindResource method as suggested by @Default:

public static object TryFindResource(this FrameworkElement element, object resourceKey)
{
    if (element == null)
        return Application.Current.Resources[resourceKey];

    var resource = element.Resources[resourceKey];
    if (resource != null)
    {
        return resource;
    }
    return TryFindResource(element.Parent, resourceKey);
}

UWP ResourceDictionary Style Error: The parameter is incorrect

Custom types used as resources can’t have the UIElement class in their inheritance, because a UIElement can never be shareable (it’s always intended to represent exactly one UI element that exists at one position in the object graph of your runtime app).

<Style x:Key="ME_BASE_AppbarButtonSaveStyle" TargetType="AppBarButton">
    <Setter Property="Label" Value="Save" />
    <Setter Property="ToolTipService.ToolTip" Value="Save" />
    <Setter Property="ContentTemplate">
        <Setter.Value>
            <DataTemplate>
                <FontIcon FontFamily="Segoe MDL2 Assets"
              Glyph="&#xE105;" />
            </DataTemplate>
        </Setter.Value>
    </Setter>
</Style>

Can you define multiple TargetTypes for one XAML style?

下面的XAML片段是给WPF的,但是对UWP也有参考意义:

<Style x:Key="Highlight" TargetType="{x:Type Control}">
    <Setter Property="Foreground" Value="Red"/>
</Style>

...

<Button Style="{StaticResource Highlight}" Content="Test"/>
<TextBox Style="{StaticResource Highlight}" Text="Test"/>
<CheckBox Style="{StaticResource Highlight}" Content="Test"/>

WPF Databinding the negative of a boolean

  • Use a DataTrigger
  • Implement a iValueConverter
            <Style.Triggers>
                <DataTrigger Binding="{Binding ElementName=cb, Path=IsChecked}" Value="True">
                    <Setter Property="TextBox.IsEnabled" Value="False"/>
                </DataTrigger>
                <DataTrigger Binding="{Binding ElementName=cb, Path=IsChecked}" Value="False">
                    <Setter Property="TextBox.IsEnabled" Value="True"/>
                </DataTrigger>
            </Style.Triggers>
        </Style>

Conditional XAML

Conditional XAML provides a way to use the ApiInformation.IsApiContractPresent method in XAML markup. This lets you set properties and instantiate objects in markup based on the presence of an API without needing to use code behind. It selectively parses elements or attributes to determine whether they will be available at runtime. Conditional statements are evaluated at runtime, and elements qualified with a conditional XAML tag are parsed if they evaluate to true; otherwise, they are ignored.

WPF ControlTemplate breaks style

WPF considers ControlTemplates to be a boundry, and will not apply implicit styles (styles without an x:Key) inside of templates. But there is one exception to this rule: anything that inherits from Control will apply implicit styles.

One way to get around this is to add an implicit style in the ControlTemplate.Resources that is BasedOn the existing implicit TextBlock style:

    <ControlTemplate.Resources>
        <Style TargetType="{x:Type TextBlock}" 
               BasedOn="{StaticResource {x:Type TextBlock}}" />
    <ControlTemplate.Resources>

Place the implicit style in <Application.Resources>. Styles placed here will apply to your entire application, regardless of template boundaries. Be careful with this though, as it will apply the style to TextBlocks inside of other controls as well,

<Application.Resources>
    <Style TargetType="{x:Type TextBlock}">
        <Setter Property="Foreground" Value="Green" />
    </Style>
</Application.Resources>

Use a Label instead of a TextBlock since it’s inherited from Control, so will apply implicit Styles defined outside the ControlTemplate

Give the base style an x:Key and use it as the base style for an implicit TextBlock styles inside the ControlTemplate. It’s pretty much the same as the top solution, however it’s used for base styles that have an x:Key attribute

<Style x:Key="BaseTextBlockStyle" TargetType="{x:Type TextBlock}">
    <Setter Property="Foreground" Value="Green" />
</Style>

...

<ControlTemplate.Resources>
    <Style TargetType="{x:Type TextBlock}" 
        BasedOn="{StaticResource BaseTextBlockStyle}" />
<ControlTemplate.Resources>

UWP Changing style of AppBarButton breaks the dynamic overflow’s automatic styling

As you’ve known, while an AppBarButton is added into SecondaryCommands, it will display in Popup. And if you check with Live Visual Tree in Visual Studio, you will find the AppBarButton is added in to a CommandBarOverflowPresenter named “SecondaryItemsControl”.

参考链接

(本篇完)

Categories

Tags

comments powered by Disqus