将属性绑定到ResourceDictionary上定义的样式以消除代码重复

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了将属性绑定到ResourceDictionary上定义的样式以消除代码重复相关的知识,希望对你有一定的参考价值。

我有以下XAML代码:

<Window x:Class="LinkButton.MainWindow"
        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="clr-namespace:LinkButton"
        mc:Ignorable="d"
        Title="MainWindow" Height="350" Width="525"
        DataContext="{StaticResource MainWindowVM}">

    <Window.Resources>
        <Style TargetType="TextBlock">
            <Setter Property="Margin" Value="10" />
        </Style>
    </Window.Resources>

    <Grid>

        <Grid.ColumnDefinitions>
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition Width="Auto" />
            <ColumnDefinition />
        </Grid.ColumnDefinitions>

        <Grid.RowDefinitions>
            <RowDefinition Height="Auto" />
            <RowDefinition Height="Auto" />
        </Grid.RowDefinitions>

        <TextBlock Grid.Row="0" Grid.Column="0" Text="ddk" />
        <TextBlock Grid.Row="0" Grid.Column="1" >
             <Hyperlink Command="{Binding Link}"  
                       CommandParameter="{Binding}"
                       Foreground="Blue" >
               <Hyperlink.Inlines>
                   <TextBlock>
                        <TextBlock.Style>
                            <Style>
                                <Setter Property="TextBlock.Text" Value="{Binding Description01.Header}" />
                            </Style>
                        </TextBlock.Style>
                   </TextBlock>
               </Hyperlink.Inlines>
                </Hyperlink>
        </TextBlock>
        <TextBlock Grid.Row="1" Grid.Column="0" Text="dde" />
        <TextBlock Grid.Row="1" Grid.Column="1">
            <Hyperlink Command="{Binding Link}"  
                       CommandParameter="{Binding}"
                       Foreground="Blue" >
               <Hyperlink.Inlines>
                   <TextBlock>
                        <TextBlock.Style>
                            <Style>
                                <Setter Property="TextBlock.Text" Value="{Binding Description11.Header}" />
                            </Style>
                        </TextBlock.Style>
                   </TextBlock>
               </Hyperlink.Inlines>
                </Hyperlink>
        </TextBlock>
    </Grid>
</Window>

和C#代码:

public class TestCommand : ICommand
{
    public delegate void ICommandOnExecute(object parameter);
    public delegate bool ICommandOnCanExecute(object parameter);

    private ICommandOnExecute _execute;
    private ICommandOnCanExecute _canExecute;

    public TestCommand(ICommandOnExecute onExecuteMethod, ICommandOnCanExecute onCanExecuteMethod)
    {
        _execute = onExecuteMethod;
        _canExecute = onCanExecuteMethod;
    }

    #region ICommand Members

    public event EventHandler CanExecuteChanged
    {
        add { CommandManager.RequerySuggested += value; }
        remove { CommandManager.RequerySuggested -= value; }
    }

    public bool CanExecute(object parameter)
    {
        return _canExecute.Invoke(parameter);
    }

    public void Execute(object parameter)
    {
        _execute.Invoke(parameter);
    }

    #endregion
}

public class LongDescription
{
    public string Header { get; }
    public string Description { get; }
    public LongDescription(string header, string description)
    {
        Header = header;
        Description = description;
    }
}

public class MainWindowVM
{



    public ICommand Link => new TestCommand(ExecuteCommand1, CanExecuteCommand1);

    public LongDescription Description11 => new LongDescription("cell11", "result cell11");
    public LongDescription Description01 => new LongDescription("cell01", "result cell01");

    public bool CanExecuteCommand1(object parameter)
    {
        return true;
    }

    public void ExecuteCommand1(object parameter)
    {
        MessageBox.Show("Executing command 1");
    }

}

很明显,我在XAML(<Hyperlink.Inlines>等)中有重复的代码。我想重构它,以便消除代码重复。为此,我正在考虑在<Hyperlink.Inlines>中定义ResourceDictionary样式,然后将其绑定到MainWindowVM中的适当属性。

但我不确定如何做,任何想法?

答案

您可以像这样在ResourceDictionary中轻松移动Style

<ResourceDictionary xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
                xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml">

    <!-- Key is required to identify the Style -->
    <Style x:Key="Bind01" TargetType="TextBlock">
        <Setter Property="Text" Value="{Binding Description01.Header}" />
    </Style>

    <Style x:Key="Bind11" TargetType="TextBlock">
        <Setter Property="Text" Value="{Binding Description11.Header}" />        
    </Style>
</ResourceDictionary>

并在窗口中合并字典以使用样式

<Window.Resources>
    <ResourceDictionary>
        <ResourceDictionary.MergedDictionaries>
            <ResourceDictionary Source="YourDictionaryHere"/>
        </ResourceDictionary.MergedDictionaries>

    <Style TargetType="TextBlock">
        <Setter Property="Margin" Value="10" />
    </Style>
    </ResourceDictionary>
</Window.Resources>

使用

<TextBox Style="{DynamicResource Bind01}"/>

简单化

我建议将变量Bindings直接写入Control并将其余部分定义为Style,而不是将变量Binding放入样式(或字典)中。

更具体:以下标记将绑定字符串显示为Hyperlink,单击时执行ICommand。

    <TextBlock>
        <Hyperlink Command="{Binding Link}"  
                   CommandParameter="{Binding}"
                   Foreground="Blue" >
           <Hyperlink.Inlines>
               <TextBlock>
                    <TextBlock.Style>
                        <Style>
                            <Setter Property="TextBlock.Text" Value="{Binding Description11.Header}" />
                        </Style>
                    </TextBlock.Style>
               </TextBlock>
           </Hyperlink.Inlines>
            </Hyperlink>
    </TextBlock>

我们可以为Button定义一个Style,它看起来(并且确实)相同,但是变量Binding可以通过Content直接设置。

按钮样式

    <Style x:Key="LinkStyle" TargetType="Button">
        <Setter Property="Template">
            <Setter.Value>
                <ControlTemplate TargetType="Button">
                    <TextBlock>
                        <Hyperlink Command="{Binding Link}" CommandParameter="{Binding}">
                            <Run Text="{TemplateBinding Content}"/>
                        </Hyperlink>
                    </TextBlock>
                </ControlTemplate>
            </Setter.Value>
        </Setter>
    </Style>

将样式应用于网格中的元素(将TextBlock替换为样式按钮)

    <TextBlock Grid.Row="0" Grid.Column="0" Text="ddk" />
    <Button Grid.Row="1" Grid.Column="1" 
            Content="{Binding Description01.Header}" 
            Style="{DynamicResource LinkStyle}">
    <TextBlock Grid.Row="1" Grid.Column="0" Text="dde" />
    <Button Grid.Row="1" Grid.Column="1" 
            Content="{Binding Description11.Header}" 
            Style="{DynamicResource LinkStyle}">

屏幕(虚线为网格线)

Runtime

编辑

要设置CommandHyperlink,我们使用Button的Command属性来设置Binding。因此,我们必须在我们的风格中添加一个TemplateBinding。用Command替换“Hard Coded”TemplateBindingButton Command。对Commandparameter执行相同操作。

             <Hyperlink Command="{TemplateBinding Command}"  
                   CommandParameter="{Templatebinding Commandparameter}"
                   Foreground="Blue" >

并设置CommandCommandParameter在风格的Button

    <TextBlock Grid.Row="0" Grid.Column="0" Text="ddk" />
<Button Grid.Row="1" Grid.Column="1" 
        Content="{Binding Description01.Header}"
        Command="{Binding YOURCOMMANDHERE}"
        CommandParameter="{YOURPARAMETER}" 
        Style="{DynamicResource LinkStyle}">
<TextBlock Grid.Row="1" Grid.Column="0" Text="dde" />
<Button Grid.Row="1" Grid.Column="1" 
        Content="{Binding Description11.Header}"
        Command="{Binding YOUROTHERCOMMANDHERE}"
        CommandParameter="{YOUROTHERPARAMETER}"
        Style="{DynamicResource LinkStyle}">

以上是关于将属性绑定到ResourceDictionary上定义的样式以消除代码重复的主要内容,如果未能解决你的问题,请参考以下文章

从 Catel WPF UserControl 中的 ResourceDictionary 中绑定

如何在XAML中直接用IValueConverter绑定ResourceDictionary的值?

将 ResourceDictionary 添加到类库

ResourceDictionary 在单独的程序集中

将 XAML 中的可见性绑定到可见性属性

springboot1.x和2.x将配置属性绑定到对象上